为什么在类作用域中以什么顺序定义变量并不重要?

Why doesn't it matter in which order define variables in class scope?

提问人:Jibel 提问时间:6/8/2023 最后编辑:Jibel 更新时间:8/18/2023 访问量:460

问:

如果我们在任何函数中执行这样的两行,我们都会得到一个错误,这是合乎逻辑的,因为变量是在初始化后定义的:ba = b

int a = b;
int b = 0;

但是当我们将这两行插入到类的作用域中时,为什么类不关心定义哪个顺序呢?b

class Foo
{
    int a = b;
    int b = 0;
};
C++ 变量 范围 初始化

评论

1赞 463035818_is_not_an_ai 6/8/2023
顺便说一句,只是定义类的两个关键字。唯一的区别是成员的默认访问权限structclass
1赞 Alan Birtles 6/8/2023
请注意,大多数编译器都会警告此错误:godbolt.org/z/YfMGo9P8j
0赞 463035818_is_not_an_ai 8/18/2023
坦率地说,您(很久以前)接受了答案,现在开始赏金以获得更详细的答案,这有点奇怪。你能指出你从现有答案中缺少什么吗?
0赞 Jibel 8/18/2023
@463035818_is_not_an_ai我想更详细地了解编译器如何在类中执行此初始化

答:

13赞 Some programmer dude 6/8/2023 #1

当您定义两个非成员变量时,它们将立即初始化。

定义两个成员变量时,初始化将在构造对象时发生,而不是在定义变量时发生。

但是,初始化是按声明顺序进行的,因此 的初始化将使用未初始化和不确定的值,其值会导致未定义的行为ab

评论

0赞 Jibel 6/8/2023
所以这种初始化方式总是对 ?a
3赞 463035818_is_not_an_ai 6/8/2023
@Jibel并非总是如此。如果你交换他们的声明,它们会以正确的顺序初始化,一切都很好
14赞 463035818_is_not_an_ai 6/8/2023 #2

在类中声明成员的顺序确实很重要。

顺序决定了它们的初始化顺序。使用示例中的默认初始值设定项大致等同于将此构造函数与成员初始值设定项列表一起使用:

class Foo
{
    int a;
    int b;
    Foo() : a(b) , b(0) {}   // !! undefined !!
};

在这里,初始化顺序仍然由成员的声明顺序决定,而不是由它们在成员初始值设定项列表中的顺序决定。编译器通常会在顺序不同时发出警告。不过,在上面,问题变得更加明显:是用 before 初始化的。在初始化之前读取是未定义的行为。abbb

要正确地将一个成员的值初始化为另一个成员,您必须遵循以下顺序:

class Foo
{
    int b = 0;  // initialized first
    int a = b;  // OK
};
7赞 x6dec3fb8 6/8/2023 #3

我想补充一点:

非限定名称查找中,“成员函数定义”部分说:

对于成员函数主体内部使用的名称、成员函数的默认参数、成员函数的异常规范或默认成员初始值设定项,搜索的范围与类定义中搜索的范围相同,只不过考虑了类的整个范围,而不仅仅是使用该名称的声明之前的部分。

因此,您甚至可以在类中声明之前在此处使用。b


更新:就像其他答案所说的那样,用 初始化,但 before 被初始化。查看 https://godbolt.org/z/MT86nd3Yr,您会发现它实际上包含垃圾值。abba