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没有预料到的一个副作用。很好。也许可以解释为什么我以前没有在任何例子中看到它!