获取未初始化对象成员的地址是否定义明确?

Is taking the address of a member of an uninitialized object well defined?

考虑以下示例。当构造 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 about passing a reference to an uninitialized object but it's not quite the same thing. In this case, I'm using the 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.y 传递给 foo 的构造函数,甚至可以复制指针 - 您可以使用 x(p_x).

解引用 指针在 foo 的构造函数中的行为未定义。 (但你不会那样做。)

首先让我们把问题准确化。

您正在做的不是使用未初始化的对象,您使用的是不在其生命周期内的对象。 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 的求值也是一个左值。然后我们得出结论,没有对象的值被访问,这是明确定义的。