c++ 在初始化常量成员之前使用,这是gcc和clang的预期行为吗?

vaj7vani  于 2022-12-24  发布在  其他
关注(0)|答案(2)|浏览(181)

考虑下面的代码片段。类test有一个常量成员a和一个返回a的成员函数fun。一个初始化列表用于在构造函数中初始化a。但是在初始化列表中,一个lambda用于初始化a,返回值为fun。这会导致clang和gcc在编译和运行时的不同行为,这取决于优化级别。下面列出了代码段和编译和运行时的不同输出。这是gcc和clang的预期行为吗?

#include <iostream>

class test{
    public:
    const int a;

    test(): a([this](){return fun();}()) {}

    int fun()
    {
        return a;
    }
};

int main()
{
    auto t = test();
    std::cout << t.a << '\n';
    return 0;
}

编译时间:
一个一个一个一个一个x一个一个二个一个x一个一个三个一个x一个一个x一个四个一个
运行时间:

clang++-5.0 -std=c++17 -Wall -Wextra -Weverything

0
clang++-5.0 -std=c++17 -Wall -Wextra -Weverything -O1

4196112
g++ -std=c++17 -Wall -Wextra -Wpedantic

Non deterministic output.
g++ -std=c++17 -Wall -Wextra -Wpedantic -O1

0
jogvjijk

jogvjijk1#

我不太明白一个问题,但它似乎像你实际上是问'为什么gcc没有警告你,直到你出现了优化'。
这是众所周知的事情。在复杂情况下检测未定义行为需要编译器端付出相当多的努力,并且通常只有在优化代码时才能完成(因为编译器无论如何都要做很多工作)。只是在处理真实的生活中的编译器时要记住的事情。

xdnvmnnf

xdnvmnnf2#

您有未定义的行为。您在初始化之前使用了a的值。如果您希望您的程序有效,请在使用之前初始化您的变量。

struct test {
    int a;

    test(): a(0) { //     Effectively return the value of a,
                   //     which is 0 at this point.
        //          ~~~~~~~v~~~~
        a = [this]{ return fun(); }();
    }

    int fun()
    {
        return a;
    }
};

int main()
{
    auto t = test();
    std::cout << t.a << '\n';
    return 0;
}

你的编译器甚至警告你关于你的代码。听听他们。警告是正确的,你的代码是无效的。

相关问题