我在《C++ 编程语言》第 4 版中了解了花括号分隔的初始化程序。 > 第 2 章:C++ 之旅:基础知识。
我引用了下面的书。
The = form is traditional and dates back to C, but if in doubt, use the general {} -list form (§6.3.5.2). If nothing else, it saves you from conversions that lose information (narrowing conversions; §10.5):
int i1 = 7.2; // i1 becomes 7 int i2 {7.2}; // error : floating-point to integer conversion int i3 = {7.2}; // error : floating-point to integer conversion (the = is redundant)
但是,我无法重现这些结果。
我有以下代码。
#include <iostream>
int main()
{
int i1 = 7.2;
int i2 {7.2};
int i3 = {7.2};
std::cout << i1 << "\n";
std::cout << i2 << "\n";
std::cout << i3 << "\n";
}
当我编译并运行它时,我没有收到任何错误。我收到关于 std=c++11
的警告,但没有错误。
$ g++ init.cpp
init.cpp: In function ‘int main()’:
init.cpp:6:12: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
int i2 {7.2};
^
$ ./a.out
7
7
7
此外,警告仅针对第二个分配,但没有针对第三个分配的警告。这似乎表明 =
并不是书中提到的真正多余的。如果 =
是多余的,则第二个和第三个分配都会产生警告,或者两者都不会产生警告。
然后我用 -std=c++11
标志编译它们。
$ g++ -std=c++11 init.cpp
init.cpp: In function ‘int main()’:
init.cpp:6:16: warning: narrowing conversion of ‘7.2000000000000002e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
int i2 {7.2};
^
init.cpp:7:18: warning: narrowing conversion of ‘7.2000000000000002e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
int i3 = {7.2};
^
$ ./a.out
7
7
7
仍然没有错误。只有警告。尽管在这种情况下,第二个和第三个分配在生成警告方面表现相同。
所以我的问题是:虽然书上提到第二个和第三个赋值是错误的,但是为什么这段代码编译不通过呢?
最佳答案
这是不正确的,应该有诊断,但是它可以是警告(您收到)或错误。 gcc made this a warning for several versions due to porting issue from C++03 :
The standard only requires that "a conforming implementation shall issue at least one diagnostic message" so compiling the program with a warning is allowed. As Andrew said, -Werror=narrowing allows you to make it an error if you want.
G++ 4.6 gave an error but it was changed to a warning intentionally for 4.7 because many people (myself included) found that narrowing conversions where one of the most commonly encountered problems when trying to compile large C++03 codebases as C++11. Previously well-formed code such as char c[] = { i, 0 }; (where i will only ever be within the range of char) caused errors and had to be changed to char c[] = { (char)i, 0 }
但现在最新版本的 gcc 和 clang 使这成为一个错误,see it live for gcc .
引用 draft C++11 standard 8.5.4
[dcl.init.list] 节说:
Otherwise, if the initializer list has a single element, the object or reference is initialized from that element; if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed. [ Example:
int x1 {2}; // OK int x2 {2.0}; // error: narrowing
—end example ]
和:
A narrowing conversion is an implicit conversion
- from a floating-point type to an integer type, or
[...]
[ Note: As indicated above, such conversions are not allowed at the top level in list-initializations.—end note ] [ Example:
[...]
int ii = {2.0}; // error: narrows
[...]
所以浮点到整数的转换是一种窄化转换,格式不正确。
和部分 1.4
实现合规性 [intro.compliance] 说:
Although this International Standard states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:
[...]
- If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.
[...]
告诉我们只需要诊断。
关于c++ - 为什么与花括号分隔的初始化程序一起使用的缩小转换不会导致错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31685132/