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

Marking std::unique_ptr class member as const

本文关键字:成员 记为 const ptr std unique      更新时间:2023-10-16

很多使用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上调用)。

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

由于std::unique_ptr(对象的唯一所有权)的性质,它需要没有任何复制构造函数。move构造函数(6)只接受非const右值引用,这意味着如果你试图让你的_child const并移动它,你会得到一个很好的编译错误:)

即使自定义unique_ptr将接受const右值引用,也不可能实现。

缺点与任何const成员一样:赋值和移动赋值操作符不能正常工作(它们需要您覆盖_child),并且从父类移动不会窃取_child(性能错误)。这样的代码也不常见,可能会让人感到困惑。

增益是边际的,因为_childprivate,因此只能从Parent内部访问,因此围绕更改_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
}

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

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