C++ 将std::unique_ptr类成员标记为const
使用C++ 将std::unique_ptr类成员标记为const,c++,c++11,smart-pointers,unique-ptr,ownership,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; }; 类父类 { 公众: 父项(子项和子项): _子(std::make_uniq
std::unique_ptr
管理类依赖项所有权的许多示例如下所示:
class Parent
{
public:
Parent(Child&& child) :
_child(std::make_unique<Child>(std::move(child))){}
private:
std::unique_ptr<Child> _child;
};
类父类
{
公众:
父项(子项和子项):
_子(std::make_unique(std::move(child))){
私人:
std::唯一的ptr子项;
};
我的问题是将\u child
成员标记为const
是否会产生任何意外的副作用?(除了确保reset()
,release()
等不能在\u child
上调用之外)
我问,因为我还没有在示例中看到它,也不知道这是故意的还是仅仅为了简洁/一般性。因为std::unique_ptr(对象的唯一所有权)的性质,它要求没有任何副本构造函数。(6)只接受非常量值引用,这意味着如果您试图使您的
\u子对象常量并移动它,您将得到一个很好的编译错误:)
即使自定义的unique\u ptr
将采用常量值引用,也不可能实现。缺点与任何const
成员类似:赋值和移动赋值运算符不能正常工作(它们将要求您覆盖\u子项
)而且从父对象移动不会窃取子对象(性能缺陷)。而且,像这样编写代码是不常见的,可能会让人感到困惑
收益是微乎其微的,因为\u child
是私有的
,因此只能从父级
内部访问,因此可以打破围绕更改\u child
的不变量的代码量仅限于需要以任何方式维护不变量的成员函数和朋友
我无法想象这样一种情况:得不偿失,但如果你这样做了,你肯定可以按照自己的方式完成,而不会破坏程序的其他部分。是的,你可以这样做,这也是我在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
}
命名空间用户界面{
类MyWidget
}
类MyWidget:publicqwidget
{
Q_对象
const std::唯一的\u ptr ui;
公众:
显式MyWidgetQWidget*parent=0)
:ui(新ui::MyWidget{})
{
}
~MyWidgetQWidget();
//在实现文件中定义为默认值的析构函数,
//其中Ui::MyWidget已完成
}
这与在C++03代码中编写Ui::MyWidget*const Ui
非常相似
上面的代码创建了一个新对象,但是没有理由不使用问题中的std::move()
传递一个对象。问问自己:如果它是const
它可以从中移动吗?你是说有很多例子无法编译吗?你展示的那一个当然是。特别是,\u child(std::move(child))
part毫无意义。试图移动一个const
unique\ptr将无法编译,因为复制被删除,并且没有构造函数接受const-rvalue ref.@IgorTandetnik这根本不是我的意思-两个版本都可以编译:)问问自己:耶稣会做什么?@nwp为什么不呢?它不会试图复制或移动父对象@nwp的实例,因为它通过移动的非常量子对象@igortandtnik>构造了一个唯一的\u ptr
,问题中没有任何内容说明父对象必须是可移动的,并且可以被移动。不多,正如@nwp所说,当前的实现允许移动到const unique\u ptr中,但这阻止了对父对象的任何复制或移动操作,因为const unique ptr不允许它。@nwp问,使\u child
成员const有什么“意外的副作用”。渲染Parent
不可移动是OP没有预料到的一个副作用。很好。也许可以解释为什么我以前没有在任何例子中看到它!