使用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
等。
我问,因为我还没有在一个例子中看到它,不知道这是故意的还是仅仅是为了简洁/普遍。
答案 0 :(得分:6)
由于std::unique_ptr
(对象的唯一所有权)的性质,因此无需任何复制构造函数。 move constructor(6)只接受非const rvalue-references,这意味着如果你试图创建_child
const
并移动它,你会得到一个很好的编译错误: )
即使自定义unique_ptr
采用const rvalue-reference,也无法实现。
答案 1 :(得分:1)
缺点就像任何const
成员一样:分配和移动分配操作员无法正常工作(他们需要您覆盖_child
)并且从父母那里移动不会窃取_child
(性能错误)。编写这样的代码也很常见,可能让人感到困惑。
增益很小,因为_child
是private
,因此只能从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()
传递一个。