简体   繁体   English

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

[英]Marking std::unique_ptr class member as const

A lot of the examples for using std::unique_ptr to manage ownership of class dependencies look like the following: 使用std::unique_ptr管理类依赖项所有权的许多示例如下所示:

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

My question is whether marking the _child member as const have any unexpected side effects? 我的问题是将_child成员标记为const是否有任何意想不到的副作用? (Aside from being ensuring that reset() , release() etc. cannot be called on _child ). (除了确保无法在_child上调用reset()release()等)。

I ask since I have not yet seen it in an example and don't whether that is intentional or just for brevity/generality. 我问,因为我还没有在一个例子中看到它,不知道这是故意还是仅仅是为了简洁/普遍。

Because of the nature of a std::unique_ptr (sole ownership of an object) it's required to have no copy constructor whatsoever. 由于std::unique_ptr (对象的唯一所有权)的性质,因此无需任何复制构造函数。 The move constructor (6) only takes non-const rvalue-references which means that if you'd try to make your _child const and move it you'd get a nice compilation error :) 移动构造函数 (6)只接受非const rvalue-references,这意味着如果你试图使你的_child const移动它,你会得到一个很好的编译错误:)

Even if a custom unique_ptr would take a const rvalue-reference it would be impossible to implement. 即使自定义unique_ptr采用const rvalue-reference,也无法实现。

The downsides are like with any const member: That the assignment and move-assignment operators don't work right (they would require you to overwrite _child ) and that moving from the parent would not steal the _child (performance bug). 缺点就像任何const成员一样:赋值和移动赋值运算符不能正常工作(它们需要你覆盖_child ),而且从父级移动不会窃取_child (性能错误)。 Also it is uncommon to write code like this, possibly confusing people. 编写这样的代码也很常见,可能会让人感到困惑。

The gain is marginal because _child is private and therefore can only be accessed from inside the Parent , so the amount of code that can break invariants revolving around changing _child is limited to member functions and friends which need to be able to maintain invariants anyways. 增益是微不足道的,因为_childprivate ,因此只能从Parent内部访问,因此可以打破围绕更改_child不变量的代码量仅限于需要能够维护不变量的成员函数和朋友。

I cannot imagine a situation where the gain would outweigh the downsides, but if you do you can certainly do it your way without breakage of other parts of the program. 我无法想象收益会超过下行的情况,但如果你这样做,你当然可以按照自己的方式去做,而不会破坏程序的其他部分。

Yes, you can do this, and it's what I regularly do when implementing UI classes in Qt: 是的,你可以这样做,这是我在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
}

It's exactly comparable to writing Ui::MyWidget *const ui in C++03 code. 它与在C ++ 03代码中编写Ui::MyWidget *const ui完全相同。

The above code creates a new object, but there's no reason not to pass one in using std::move() as in the question. 上面的代码创建了一个新对象,但没有理由不在问题中使用std::move()传递一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM