gpt4 book ai didi

c++ - 这个 C++ 成员初始化行为是否定义良好?

转载 作者:IT老高 更新时间:2023-10-28 21:47:11 26 4
gpt4 key购买 nike

假设我们有一个类 B,它有一个默认初始化为 42member。此类知道如何打印其 member 的值(它在构造函数中这样做):

struct B
{
B() : member(42) { printMember(); }

void printMember() const { std::cout << "value: " << member << std::endl; }

int member;
};

然后我们添加一个类 A,它接收一个对 B 的 const 引用并要求 B 打印它的值:

struct A
{
A(const B& b) { b.printMember(); }
};

最后我们添加另一个类Aggregate,它聚合了一个A 和一个B。棘手的部分是 A 类型的对象 a 是在对象 b 类型 B 之前声明的,然后是 >a 使用对 b 的(尚未生效的?)引用进行初始化:

struct Aggregate
{
A a;
B b;

Aggregate() : a(b) { }
};

考虑创建 Aggregate 的输出(我在 AB 的构造函数和析构函数中都添加了一些日志记录)(Try it online! ):

a c'tor
value: 0
b c'tor
value: 42
b d'tor
a d'tor

我是否正确假设使用 b 的(尚未有效的)实例初始化 a 是无效的,因此这是未定义的行为?


我知道初始化顺序。这就是让我挣扎的原因。我知道 b 还没有被构造,但我也认为 知道b 的 future 地址可以甚至在构造 b 之前就已确定。因此我假设 可能有一些我不知道的规则允许编译器在 b 之前默认初始化 b 的成员建筑或类似的东西。 (如果第一个打印出来的值看起来是随机的,而不是 0(int 的默认值),那会更明显。


This answer 帮助我理解我需要区分

  • 将引用绑定(bind)到未初始化的对象(有效)和
  • 通过引用访问一个未初始化的对象(未定义)

最佳答案

是的,你是对的,它是 UB ,但出于不同的原因,不仅仅是存储对尚未构造的对象的引用。

类成员的构造按照它们在类中出现的顺序进行。虽然 B 的地址不会改变,从技术上讲你是 can store a reference to it ,正如@StoryTeller 指出的那样,在构造函数中调用 b.printMember()b 还没构建的肯定是UB。

关于c++ - 这个 C++ 成员初始化行为是否定义良好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52035310/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com