这是 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->_uptrIntBuilder::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() {}
};