考虑以下示例。当 bar
被构造时,它为它的基类型 (foo
) 构造函数提供了 my_member.y
的地址,其中 my_member
是尚未初始化的数据成员。
struct foo {
foo(int * p_x) : x(p_x) {}
int * x;
};
struct member {
member(int p_y) : y(p_y) {}
int y;
};
struct bar : foo
{
bar() : foo(&my_member.y), my_member(42) {}
member my_member;
};
#include <iostream>
int main()
{
bar my_bar;
std::cout << *my_bar.x;
}
这个定义好吗?获取未初始化对象的数据成员的地址是否合法?我找到了 this question关于传递对未初始化对象的引用,但这并不完全相同。在这种情况下,我使用的是 member access operator .
在未初始化的对象上。
的确,对象数据成员的地址不应该通过初始化更改,但这并不一定使采用该地址得到很好的定义。此外,member access operators 上的 ccpreference.com 页面有这样说:
The first operand of both operators is evaluated even if it is not necessary (e.g. when the second operand names a static member).
我理解这意味着在 &my_member.y
的情况下 my_member
将被评估,我认为这很好(比如 int x; x;
似乎很好)但我也找不到支持它的文档。
最佳答案
首先让我们把问题准确化。
您正在做的不是使用未初始化的对象,您使用的是不在其生命周期内的对象。 my_member
是在 foo
之后构造的,因此 my_member
的生命周期还没有从 foo(&my_member.y)
开始.
来自 [basic.life]
before the lifetime of an object has started but after the storage which the object will occupy has been allocated [...], any glvalue that refers to the original object may be used but only in limited ways. [...] such a glvalue refers to allocated storage, and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
- the glvalue is used to access the object, or [...]
这里访问它具体是指读取或修改对象的值。
my_member
的计算产生了一个左值,并且不需要转换为纯右值,因此它仍然是一个左值。同样,my_member.y
的评估也是一个左值。然后我们得出结论,没有对象的值被访问过,这是明确定义的。
关于c++ - 获取未初始化对象成员的地址是否定义明确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54206796/