【问题标题】:Marking std::unique_ptr class member as const将 std::unique_ptr 类成员标记为 const
【发布时间】:2017-01-15 04:43:01
【问题描述】:

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

我问是因为我还没有在示例中看到它,并且不知道这是故意的还是只是为了简洁/概括。

【问题讨论】:

  • 扪心自问:如果是const,可以移出吗?
  • 你是说有很多编译失败的例子?你展示的那个当然可以。特别是,_child(std::move(child)) 部分毫无意义。
  • 尝试移动 const unique_ptr 将无法编译,因为复制被删除并且没有构造函数接受 const rvalue ref。
  • @IgorTandetnik 这根本不是我的意思——两个版本都编译得很好:)
  • 问问自己:耶稣会做什么?

标签: c++ c++11 smart-pointers unique-ptr ownership


【解决方案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() 传递一个。

【讨论】:

    【解决方案2】:

    缺点与任何const 成员一样:赋值和移动赋值运算符无法正常工作(它们会要求您覆盖_child)并且从父级移动不会窃取@987654323 @(性能错误)。而且这样写代码也不常见,可能会让人迷惑。

    收益是微不足道的,因为_childprivate,因此只能从Parent 内部访问,因此可以破坏围绕更改_child 的不变量的代码量仅限于成员函数和朋友无论如何都需要能够保持不变量。

    我无法想象收益会超过负面影响的情况,但如果您这样做,您当然可以按照自己的方式进行操作,而不会破坏程序的其他部分。

    【讨论】:

    • 好点。可能解释了为什么我以前在任何示例中都没有见过它!
    【解决方案3】:

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

    即使自定义 unique_ptr 会采用 const 右值引用,也无法实现。

    【讨论】:

    • @nwp 为什么不呢?它不会尝试复制或移动 Parent 的实例。
    • @nwp 因为它通过移动的 non const child 构造了一个unique_ptr
    • @IgorTandetnik 问题中没有任何内容表明Parent 必须是可移动的,并且可以移动。
    • 不多,正如@nwp 所说,当前实现允许移动到 const unique_ptr 但这会阻止 Parent 的任何复制或移动操作,因为 const unique ptr 不允许这样做。
    • @nwp OP 询问使 _child 成为 const 成员的“意外副作用”可能是什么。渲染 Parent 不可移动是 OP 似乎没有预料到的副作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 2014-03-27
    相关资源
    最近更新 更多