在const成员初始化之前的用法,这是gcc和clang的预期bahviour吗?

问题描述 投票:0回答:2

请考虑以下代码段。类test有一个const成员a和一个返回fun的成员函数a。初始化列表用于在构造函数中初始化a。但是在初始化列表中,lambda用于使用返回的fun值初始化a。这会导致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;
}

编译时间:

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

lambda_in_initializer_list.cpp:7:15: warning: lambda expressions are incompatible with C++98
      [-Wc++98-compat]
    test(): a([this](){return fun();}()) {}
              ^
warning: 'auto' type specifier is incompatible with C++98 [-Wc++98-compat]
lambda_in_initializer_list.cpp:17:5: warning: 'auto' type specifier is incompatible with C++98
      [-Wc++98-compat]
    auto t = test();
    ^~~~
3 warnings generated.

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

lambda_in_initializer_list.cpp:7:15: warning: lambda expressions are incompatible with C++98
      [-Wc++98-compat]
    test(): a([this](){return fun();}()) {}
              ^
warning: 'auto' type specifier is incompatible with C++98 [-Wc++98-compat]
lambda_in_initializer_list.cpp:17:5: warning: 'auto' type specifier is incompatible with C++98
      [-Wc++98-compat]
    auto t = test();
    ^~~~

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

No output

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

lambda_in_initializer_list.cpp: In function ‘int main()’:
lambda_in_initializer_list.cpp:18:20: warning: ‘t.test::a’ is used uninitialized in this function [-Wuninitialized]
     std::cout << t.a << '\n';
                  ~~^

运行:

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
c++ gcc clang compiler-warnings
2个回答
3
投票

我不太明白一个问题,但看起来你实际上在问'为什么gcc没有警告你,直到你出现优化'。

这是众所周知的事情。在复杂的情况下检测未定义的行为需要在编译器方面付出相当多的努力,并且通常只在优化代码时才会完成(因为编译器无论如何都要做很多工作)。在处理现实生活编译器时,请记住一些事项。


2
投票

你有未定义的行为。在初始化之前使用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;
}

您的编译器甚至警告过您的代码。听他们说。警告是对的,您的代码无效。

© www.soinside.com 2019 - 2024. All rights reserved.