涉及智能指针时 class 成员的 C++ 顺序很重要
C++ Order of class members when smart pointers are involved matters
考虑这个片段:
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
。
恕我直言,当涉及到智能指针时,成员的顺序很重要,不是吗?
但是这个设计是不是有点脆?
如果有人更改会员顺序怎么办?
有没有better/canonical不需要依赖成员顺序的设计,还是和RAII一样?
成员的顺序很重要。
智能指针的存在是红色的。您示例中的症结在于一个成员的初始化取决于已经初始化的其他成员。
成员按照它们在 class 定义中出现的顺序进行初始化。总是。
即使您在成员初始化器列表中以不同顺序列出它们,它们仍会按照它们在 class 定义中出现的顺序进行初始化。通常编译器会在顺序不同时发出警告。
您遇到类似的问题:
struct foo {
int x;
int y;
foo() : x(1),y(this->x * 2) {}
};
更改 x
和 y
的顺序将导致初始化未定义(y
将使用未初始化的 x
)。
But is this design not somewhat brittle?
是的。当成员的初始化相互依赖时,你需要格外小心。
What if someone changes the member order?
您将收到编译器警告,最好不要忽略。
Is there a better/canonical design where there is no need of relying on the member order, or is it just like it is with RAII?
您可能不需要引用和智能指针。摆脱其中一个。因为他们都是 public
所以他们两个真的没有意义。
总的来说,评论中提出的可能是解决方案。如果将一个成员重构为基 class 的成员,那么毫无疑问初始化顺序,因为基 class 是最先初始化的。
考虑这个片段:
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
。
恕我直言,当涉及到智能指针时,成员的顺序很重要,不是吗?
但是这个设计是不是有点脆?
如果有人更改会员顺序怎么办?
有没有better/canonical不需要依赖成员顺序的设计,还是和RAII一样?
成员的顺序很重要。
智能指针的存在是红色的。您示例中的症结在于一个成员的初始化取决于已经初始化的其他成员。
成员按照它们在 class 定义中出现的顺序进行初始化。总是。
即使您在成员初始化器列表中以不同顺序列出它们,它们仍会按照它们在 class 定义中出现的顺序进行初始化。通常编译器会在顺序不同时发出警告。
您遇到类似的问题:
struct foo {
int x;
int y;
foo() : x(1),y(this->x * 2) {}
};
更改 x
和 y
的顺序将导致初始化未定义(y
将使用未初始化的 x
)。
But is this design not somewhat brittle?
是的。当成员的初始化相互依赖时,你需要格外小心。
What if someone changes the member order?
您将收到编译器警告,最好不要忽略。
Is there a better/canonical design where there is no need of relying on the member order, or is it just like it is with RAII?
您可能不需要引用和智能指针。摆脱其中一个。因为他们都是 public
所以他们两个真的没有意义。
总的来说,评论中提出的可能是解决方案。如果将一个成员重构为基 class 的成员,那么毫无疑问初始化顺序,因为基 class 是最先初始化的。