为什么不缩小转换使用与大括号分隔的初始化程序导致错误? [英] Why doesn't narrowing conversion used with curly-brace-delimited initializer cause an error?

查看:184
本文介绍了为什么不缩小转换使用与大括号分隔的初始化程序导致错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我学习了C ++编程语言中的大括号分隔初始化器,第4版。 >

I learnt about curly-brace-delimited initializer in The C++ Programming Language, 4th ed. > Chapter 2: A Tour of C++: The Basics.

我在下面的书中引用。


The形式是传统的,可追溯到C,但如果有疑问,请使用general {} -list form(§6.3.5.2)。
如果没有别的,它可以避免失去信息的转化(缩小转化;§10.5):

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)


但是,我无法重现这些结果。

However, I am unable to reproduce these results.

我有以下代码。

#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 的警告,但没有错误。

When I compile and run it, I don't get any error. I get a warning about std=c++11 but no error.

$ 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 标志编译它们。

Further, the warning is only for the second assignment but there is no warning for the third assignment. This seems to indicate that the = is not really redundant as mentioned in the book. If = were redundant, either both the second and third assignments would have produced warnings or both would not have produced warnings. Then I compile them with the -std=c++11 flag.

$ 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

仍然没有错误。只有警告。尽管在这种情况下,第二个和第三个分配在生成警告时的行为相同。

Still no error. Only warnings. Although in this case the second and third assignments behave identically with respect to generating warnings.

所以我的问题是:虽然这本书提到第二和第三个赋值是错误,为什么这个代码不能编译?

So my question is: Although the book mentions that the second and third assignments are errors, why doesn't this code fail to compile?

推荐答案

这是错误的,应该有诊断,作为警告(您收到的 )或错误。 gcc因为从C ++ 03移植问题而导致几个版本的警告

This is ill-formed and there should be diagnostic, however it can either be a warning(which you received) or an error. gcc made this a warning for several versions due to porting issue from C++03:


标准只要求一致的实施应至少发出一个诊断消息警告。如安德鲁所说,-Werror = narrowing允许你使它成为一个错误,如果你想要的。

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给出一个错误,但它被改为一个警告故意为4.7,许多人(包括我自己)发现,缩小转换,其中最常遇到的问题之一,当试图编译大型C ++ 03代码库作为C ++ 11。以前格式良好的代码,如char c [] = {i,0}; (我只会在char的范围内)引起的错误,必须更改为char c [] = {(char)i,0}

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版本使此为错误,查看它的gcc

but now recent versions of gcc and clang make this an error, see it live for gcc.

参考 draft C ++ 11标准部分 8.5.4 [dcl.init.list] / em>说:

For reference the draft C++11 standard section 8.5.4 [dcl.init.list] says:


否则,如果初始化器列表有一个元素,对象或
引用从元件;如果需要缩小转换
(见下文)将元素转换为T,程序是
格式不正确。 [示例:

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示例]

和:


缩小转换是隐式转换

A narrowing conversion is an implicit conversion


  • 从浮点类型转换为整数类型,或

...]

[注意:如上所述,列表初始化中不允许在顶层进行此类转换。-end
note] :

[ 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

[...]

因此,浮点数到整数转换是一个缩小的转换,并且是错误的。

So a floating point to integer conversion is a narrowing conversion and is ill-formed.

1.4 实施合规性[intro.compliance]说:

and section 1.4 Implementation compliance [intro.compliance] says:


虽然本国际标准仅声明对C ++实现,那些需求
通常更容易理解,如果他们被称为程序,部分程序或
执行程序的要求。此类要求具有以下含义:

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:

[...]


  • 程序包含违反任何可诊断规则或本标准中的
    描述为有条件支持的结构,当实现不支持该结构时,
    a符合实现应发出至少一个诊断

[...]

告诉我们只需要诊断。

这篇关于为什么不缩小转换使用与大括号分隔的初始化程序导致错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆