Lon*_*ner 13 c++ narrowing c++11
我在"C++编程语言"第4版中学习了大括号分隔初始化器.>第2章:C++之旅:基础知识.
我引用下面的书.
=表格是传统的并且可以追溯到C,但是如果有疑问,请使用通用{} -list表单(第6.3.5.2节).如果不出意外,它可以帮助您避免丢失信息的转换(缩小转化次数;§10.5):
Run Code Online (Sandbox Code Playgroud)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";
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行它时,我没有得到任何错误.我收到警告,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
Run Code Online (Sandbox Code Playgroud)
此外,警告仅适用于第二次分配,但第三次分配没有警告.这似乎表明,=书中提到的并不是真正多余的.如果=是多余的,则第二次和第三次分配都会产生警告,或者两者都不会产生警告.然后我用-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
Run Code Online (Sandbox Code Playgroud)
仍然没有错误.只有警告.虽然在这种情况下,第二次和第三次分配在产生警告方面的行为相同.
所以我的问题是:尽管本书提到第二和第三个赋值都是错误,为什么这个代码不能编译?
Sha*_*our 13
这是不正确的,应该有诊断,但它可能是一个警告(你收到)或错误.由于C++ 03的移植问题,gcc对几个版本发出警告:
该标准仅要求"符合要求的实现应至少发出一条诊断消息",因此允许编写程序并发出警告.正如Andrew所说,-Werror = narrowing允许你在需要时使其成为错误.
G ++ 4.6给出了一个错误,但它有意为4.7更改为警告,因为许多人(包括我自己)发现缩小转换时,在尝试编译大型C++ 03代码库时,最常遇到的问题之一是C++ 11.以前格式良好的代码,例如char c [] = {i,0}; (其中我只会在char范围内)导致错误并且必须更改为char c [] = {(char)i,0}
但现在gcc和clang的最新版本使这个错误,看到它为gcc现场直播.
作为参考,草案C++ 11标准部分8.5.4 [dcl.init.list]说:
否则,如果初始化列表具有单个元素,则从该元素初始化对象或引用; 如果需要缩小转换(见下文)将元素转换为T,则程序格式不正确.[例如:
Run Code Online (Sandbox Code Playgroud)int x1 {2}; // OK int x2 {2.0}; // error: narrowing- 末端的例子]
和:
缩小转换是隐式转换
- 从浮点类型到整数类型,或
[...]
[注意:如上所述,列表初始化中顶层不允许进行此类转换.-结尾注释] [示例:
[...]
Run Code Online (Sandbox Code Playgroud)int ii = {2.0}; // error: narrows[...]
因此,浮点到整数转换是一种缩小的转换并且是不正确的.
和部分1.4实施合规性[intro.compliance]说:
虽然本国际标准仅规定了对C++实现的要求,但如果将这些要求表达为对程序,程序部分或程序执行的要求,则这些要求通常更容易理解.这些要求具有以下含义:
[...]
- 如果程序包含违反任何可诊断规则或本标准中描述的构造的发生,如果实现不支持该构造,则符合条件的实现应发出至少一条诊断消息.
[...]
告诉我们只需要诊断.
C++语言不区分"警告"和"错误".C++只有诊断消息.您收到的警告是诊断消息.语言规范不要求编译器在遇到错误(也就是格式错误的)代码时停止编译.所有编译器必须做的是发出诊断消息,然后如果他们愿意,他们可以继续编译.
这意味着在一般情况下,您有责任告知警告"警告",这些警告实际上表示真正的错误,特别是对于像GCC这样的许可编译器.
这也意味着实际的真实行为是编译器设置的问题.如果可能的话,请求您的编译器在这方面更具限制性.在GCC中,您可以尝试-pedantic-errors切换以实现此目的.
PS在我使用GCC的实验中,-std=c++11足以使它为您的代码生成错误.如果您收到警告,则可能是编译器版本问题.