【问题标题】:C++ Order of class members when smart pointers are involved matters涉及智能指针时类成员的 C++ 顺序很重要
【发布时间】:2020-11-16 10:31:24
【问题描述】:

考虑一下这个sn-p:

struct A
{
    A(std::unique_ptr<int> somePtr_)
    : somePtr{std::move(somePtr_)},
      someInt{*somePtr}
    {};
    
    std::unique_ptr<int> somePtr;
    const int& someInt;
};

这里,传递并存储了一个unique_ptr

然后还会存储对基础数据的引用。

A 的对象被销毁时,首先someInt 超出范围,然后somePtr

恕我直言,当涉及到智能指针时,成员的顺序很重要,不是吗?

但是这个设计是不是有点脆弱?

如果有人更改会员顺序怎么办?

是否有更好/规范的设计,不需要依赖成员顺序,还是就像使用 RAII 一样?

【问题讨论】:

  • 如果有人更改了成员顺序,那么让他们自己初始化 int 引用。要谈论更好的规范设计,首先要确定为什么需要这两个,一个指针和一个引用。
  • 更好的解决方案可能是将unique_ptr 移动到(私有)基类中,或者使someInt 成为成员函数而不是数据成员。

标签: c++ smart-pointers unique-ptr raii


【解决方案1】:

成员的顺序总是很重要。

智能指针的存在是红色的。您的示例中的症结在于一个成员的初始化依赖于已经初始化的其他成员。

成员按照它们在类定义中出现的顺序进行初始化。总是。

即使您在成员初始化列表中以不同的顺序列出它们,它们仍然按照它们在类定义中出现的顺序进行初始化。并且通常编译器会在顺序不同时发出警告。

你会遇到类似的问题:

struct foo {
    int x;
    int y;
    foo() : x(1),y(this->x * 2) {}
};

更改xy 的顺序会导致初始化未定义(y 将使用未初始化的x)。

但是这个设计是不是有点脆弱?

是的。当成员的初始化相互依赖时,您需要格外小心。

如果有人更改会员顺序怎么办?

你会得到一个编译器警告,你最好不要忽略。

是否有更好/规范的设计,不需要依赖成员顺序,还是就像使用 RAII 一样?

您可能不需要引用智能指针。摆脱其中之一。因为他们都是public,所以同时拥有他们真的没有意义。

一般来说,评论中的建议可能是一个解决方案。如果你将一个成员重构为基类的成员,那么初始化的顺序毫无疑问,因为基类首先被初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-16
    • 2021-02-19
    • 1970-01-01
    • 2011-12-25
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多