这是未定义的行为还是struct init的错误?

时间:2017-12-30 15:17:45

标签: c++ struct language-lawyer object-lifetime list-initialization

请考虑这段代码:

#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,然后在调用方法和赋值时将其覆盖,另一个在最后,在所有内容之后执行。

问。对这种行为有什么解释?

谢谢。

1 个答案:

答案 0 :(得分:7)

是的,这是未定义的行为:

int foo()
{
    std::cout << "enter foo: " << this->x << "," << this->y << "," << this->z << std::endl;
    //                            ~~~~~~~           ~~~~~~~           ~~~~~~~
}       

在调用foo()时,xyz尚未初始化。来自[dcl.init]/12

  

如果没有为对象指定初始值设定项,则默认初始化该对象。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定值,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到该值被替换为止( [expr.ass])。 [...]如果评估产生了不确定的值,则行为是不确定的,除非在下列情况下:[...]

其余案件均不适用。因此,打印xyz会有未定义的行为。与众不同:

int x;
std::cout << x; // ub

我之前的回答是肯定的,但是出于终生的原因。它曾建议A b{ b.foo(), b.z = b.moo(), 3};中的初始化是非空的,因此在初始化结束之前b的任何成员的任何访问都是UB。但是,xskxzr后来告诉我,为了使初始化非空,你must have constructors invokedint没有构造函数。这使b的初始化成为空白。这在概念上对我来说很奇怪,但这方面的措辞很清楚。

相关问题