将std :: unique_ptr类成员标记为const

时间:2016-09-07 13:07:42

标签: c++ c++11 smart-pointers unique-ptr ownership

使用std::unique_ptr管理类依赖关系所有权的许多示例如下所示:

class Parent
{
public:
    Parent(Child&& child) :
    _child(std::make_unique<Child>(std::move(child))){}
private:
    std::unique_ptr<Child> _child;
};

我的问题是,将_child成员标记为const是否有任何意外的副作用? (除了确保无法在reset())上调用release()_child等。

我问,因为我还没有在一个例子中看到它,不知道这是故意的还是仅仅是为了简洁/普遍。

3 个答案:

答案 0 :(得分:6)

由于std::unique_ptr(对象的唯一所有权)的性质,因此无需任何复制构造函数。 move constructor(6)只接受非const rvalue-references,这意味着如果你试图创建_child const并移动它,你会得到一个很好的编译错误: )

即使自定义unique_ptr采用const rvalue-reference,也无法实现。

答案 1 :(得分:1)

缺点就像任何const成员一样:分配和移动分配操作员无法正常工作(他们需要您覆盖_child)并且从父母那里移动不会窃取_child(性能错误)。编写这样的代码也很常见,可能让人感到困惑。

增益很小,因为_childprivate,因此只能从Parent内部访问,因此可以打破不变量的代码量围绕更改{{1}仅限于需要能够维护不变量的成员函数和朋友。

我无法想象收益会超过下行的情况,但如果你这样做,你当然可以按照自己的方式去做,而不会破坏程序的其他部分。

答案 2 :(得分:1)

是的,你可以这样做,这是我在Qt中实现UI类时经常做的事情:

namespace Ui {
    class MyWidget
}

class MyWidget : public QWidget
{
    Q_OBJECT  

    const std::unique_ptr<Ui::MyWidget> ui;

public:
    explicit MyWidgetQWidget *parent = 0)
        : ui(new Ui::MyWidget{})
    {
    }

    ~MyWidgetQWidget();
    // destructor defined as = default in implementation file,
    // where Ui::MyWidget is complete
}

它与在C ++ 03代码中编写Ui::MyWidget *const ui完全相同。

上面的代码会创建一个新对象,但没有理由不在问题中使用std::move()传递一个。