这是 unique_ptr 的正确用法吗?
Is this proper usage of a unique_ptr?
根据我通过阅读此处查找唯一指针时弹出的大部分问题的判断,在我看来,这应该提供构建器模式所描述的行为。
我希望 Builder 的任何实例(或其子实例 类,因为它不执行任何修改正在构建的对象的过程)在关闭之前拥有正在构建的对象 returns指向调用者的唯一指针,此时调用者获得所有权。
Builder.h
template <class type> class Builder
{
public:
~Builder();
unique_ptr<type> Close();
protected:
Builder();
unique_ptr<type> _uptr;
};
Builder.cpp
template<class type> Builder<type>::Builder()
{
uptr = make_unique<type>();
}
template<class type> Builder<type>::~Builder()
{}
template<class type> unique_ptr<type> Builder<type>::Close()
{
return uptr;
}
我理解按值传递唯一指针的语义吗?
(为简洁/易读而省略了包含和命名空间)
std::unique_ptr 无法复制。相反,您必须向上移动才能正确转移底层指针的所有权。
template<class type> unique_ptr<type> Builder<type>::Close()
{
return std::move(uptr);
}
Do I understand the semantics of passing a unique pointer by value?
您可以 move 来自 unique_ptr:std::move(this->_uptr)
小心移动,因为它们会使原始对象的内容无效。
我已经完成了你的例子来举例说明威胁:
#include <iostream>
#include <memory>
template<typename T> class Builder
{
public:
virtual ~Builder() {}
std::unique_ptr<T> Close();
protected:
Builder() {}
std::unique_ptr<T> _uptr;
};
class IntBuilder: public Builder<int>
{
public:
IntBuilder() : Builder<int>() {
this->_uptr = std::unique_ptr<int>(new int);
}
void setValue(int x) {
*(this->_uptr) = x;
}
std::unique_ptr<int> Close() {
return std::move(this->_uptr);
}
};
int main() {
IntBuilder b;
b.setValue(3);
auto i = b.Close();
std::cout << *i << std::endl; // OK
auto i2 = b.Close();
std::cout << *i2 << std::endl; // Segmentation fault
}
尽管 this->_uptr
在 IntBuilder::Close()
内移动,编译器不会警告您有关段错误的可能性。
此外,我建议只使用 T Builder<T>::Close()
而不是 unique_ptr<T> Builder<T>::Close()
,因为后者只会限制 class.
的灵活性
另外,为什么不让子classes 管理他们正在创建的实例。如果他们正在创建的实例不能被改变,则 sub-class 需要存储有关实例的信息直到它被创建(在 Close()
)并且将不必要地携带 unique_ptr<T>
.
以下是我如何更改生成器 class:
template<typename T> class Builder
{
public:
virtual ~Builder() {}
T&& Close();
protected:
Builder() {}
};
根据我通过阅读此处查找唯一指针时弹出的大部分问题的判断,在我看来,这应该提供构建器模式所描述的行为。
我希望 Builder 的任何实例(或其子实例 类,因为它不执行任何修改正在构建的对象的过程)在关闭之前拥有正在构建的对象 returns指向调用者的唯一指针,此时调用者获得所有权。
Builder.h
template <class type> class Builder
{
public:
~Builder();
unique_ptr<type> Close();
protected:
Builder();
unique_ptr<type> _uptr;
};
Builder.cpp
template<class type> Builder<type>::Builder()
{
uptr = make_unique<type>();
}
template<class type> Builder<type>::~Builder()
{}
template<class type> unique_ptr<type> Builder<type>::Close()
{
return uptr;
}
我理解按值传递唯一指针的语义吗?
(为简洁/易读而省略了包含和命名空间)
std::unique_ptr 无法复制。相反,您必须向上移动才能正确转移底层指针的所有权。
template<class type> unique_ptr<type> Builder<type>::Close()
{
return std::move(uptr);
}
Do I understand the semantics of passing a unique pointer by value?
您可以 move 来自 unique_ptr:std::move(this->_uptr)
小心移动,因为它们会使原始对象的内容无效。
我已经完成了你的例子来举例说明威胁:
#include <iostream>
#include <memory>
template<typename T> class Builder
{
public:
virtual ~Builder() {}
std::unique_ptr<T> Close();
protected:
Builder() {}
std::unique_ptr<T> _uptr;
};
class IntBuilder: public Builder<int>
{
public:
IntBuilder() : Builder<int>() {
this->_uptr = std::unique_ptr<int>(new int);
}
void setValue(int x) {
*(this->_uptr) = x;
}
std::unique_ptr<int> Close() {
return std::move(this->_uptr);
}
};
int main() {
IntBuilder b;
b.setValue(3);
auto i = b.Close();
std::cout << *i << std::endl; // OK
auto i2 = b.Close();
std::cout << *i2 << std::endl; // Segmentation fault
}
尽管 this->_uptr
在 IntBuilder::Close()
内移动,编译器不会警告您有关段错误的可能性。
此外,我建议只使用 T Builder<T>::Close()
而不是 unique_ptr<T> Builder<T>::Close()
,因为后者只会限制 class.
另外,为什么不让子classes 管理他们正在创建的实例。如果他们正在创建的实例不能被改变,则 sub-class 需要存储有关实例的信息直到它被创建(在 Close()
)并且将不必要地携带 unique_ptr<T>
.
以下是我如何更改生成器 class:
template<typename T> class Builder
{
public:
virtual ~Builder() {}
T&& Close();
protected:
Builder() {}
};