请考虑这段代码:
#include <iostream>
int main()
{
struct A
{
int x;
int y;
int z;
int foo()
{
std::cout << "enter foo: " << this->x << "," << this->y << "," << this->z << std::endl;
return 5;
}
int moo()
{
std::cout << "enter moo: " << this->x << "," << this->y << "," << this->z << std::endl;
this->x = 1;
this->z = 10;
return 2;
}
};
A b { b.foo(), b.z = b.moo(), 3};
std::cout << "final: " << b.x << "," << b.y << "," << b.z << std::endl;
return 0;
}
我的 VS2017(x64 版本)中的结果:
enter foo: 0,0,0
enter moo: 5,0,0
final: 1,2,3
ideone.com (gcc 6.3) https://ideone.com/OGqvjW 的结果:
enter foo: 0,0,3
enter moo: 5,0,3
final: 1,2,2
一个编译器在所有事情之前立即将
z
成员设置为 3,然后在调用方法和赋值时覆盖它,另一个编译器在所有事情的最后这样做。问:对这种行为的解释是什么?
谢谢你。
最佳答案
是的,这是未定义的行为:
int foo()
{
std::cout << "enter foo: " << this->x << "," << this->y << "," << this->z << std::endl;
// ~~~~~~~ ~~~~~~~ ~~~~~~~
}
在调用
foo()
时, x
、 y
和 z
尚未初始化。来自 [dcl.init]/12 :其余情况均不适用。因此打印
x
、 y
和 z
存在未定义的行为。无异于:int x;
std::cout << x; // ub
我之前的回答是肯定的,但出于一生的原因。它已经表明
A b{ b.foo(), b.z = b.moo(), 3};
中的初始化是非空的,因此在初始化结束之前对 b
的任何成员的任何访问都是 UB。但是,xskxzr 已经向我表明,为了使初始化非空,您 must have constructors invoked 和 int
没有构造函数。这使得 b
的初始化变得空洞。这对我来说在概念上似乎很奇怪,但这方面的措辞很清楚。关于c++ - 这是未定义的行为还是 struct init 的错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48035195/