在 const 成员初始化之前使用,这是 gcc 和 clang 的预期行为吗?
Usage before initialization of const member, is this expected bahviour of gcc and clang?
考虑以下片段。 Class test
有一个常量成员 a
和一个成员函数 fun
其中 returns 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
您有未定义的行为。您在初始化之前使用 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;
}
您的编译器甚至警告过您的代码。听他们说。警告是正确的,您的代码无效。
我不太明白一个问题,但看起来你实际上是在问'为什么 gcc 在你打开优化之前没有警告你'。
这是众所周知的事情。在复杂情况下检测未定义的行为需要在编译器方面付出很多努力,而且通常只有在优化代码时才会这样做(因为无论如何编译器都会做很多工作)。当您处理现实生活中的编译器时,请记住一些事情。
考虑以下片段。 Class test
有一个常量成员 a
和一个成员函数 fun
其中 returns 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
您有未定义的行为。您在初始化之前使用 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;
}
您的编译器甚至警告过您的代码。听他们说。警告是正确的,您的代码无效。
我不太明白一个问题,但看起来你实际上是在问'为什么 gcc 在你打开优化之前没有警告你'。
这是众所周知的事情。在复杂情况下检测未定义的行为需要在编译器方面付出很多努力,而且通常只有在优化代码时才会这样做(因为无论如何编译器都会做很多工作)。当您处理现实生活中的编译器时,请记住一些事情。