简体   繁体   English

为什么编译器不警告unsigned to signed conversion?

[英]Why doesn't the compiler warn about unsigned to signed conversion?

I recently got bit in the butt with this code: 我最近得到了这个代码:

std::size_t s = 10;
std::vector<int> v{s};

Rather than initialize with a size of 10, this initializes with a size of 1 with one element 10 . 而不是使用10的大小初始化,而是使用一个元素10初始化大小为1。 However, the vector has an explicit constructor that takes a std::size_t . 但是,向量有一个显式构造函数,它采用std::size_t With all the hype about "use braces everywhere", I would expect many people have fallen into this trap. 随着所有关于“到处都使用括号”的炒作,我预计会有很多人陷入这个陷阱。 This could be avoided if the compiler simply warned that we were trying to turn a size_t into an int . 如果编译器只是警告我们试图将size_t转换为int ,则可以避免这种情况。

Why isn't the compiler required to do this? 为什么编译器不需要这样做?

EDIT : My original code had const std::size_t s . 编辑 :我的原始代码有const std::size_t s Apparently none of the compilers I use warn unless I remove the const. 显然,除非我删除const,否则我使用的编译器都不会发出警告。 Is this a bug? 这是一个错误吗?

No it is not a bug. 不,这不是一个bug。 See [dcl.init.list]/7 of N3337: 见N3337的[dcl.init.list] / 7:

A narrowing conversion is an implicit conversion 缩小转换是隐式转换

... ...

  • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type. 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非source是常量表达式,并且转换后的实际值将适合目标类型并且将在生成原始值时生成原始值转换回原始类型。

Therefore the code is valid so long as s is const . 因此,只要sconst ,代码就是有效的。

Rather than initialize with a size of 10, this initializes with a size of 1 with one element 10 而不是使用10的大小初始化,而是使用一个元素10初始化大小为1

First initializer-list are gready: 第一个初始化列表是gready:

§13.3.1.7 [over.match.list]/p1: §13.3.1.7[over.match.list] / p1:

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases: 当非聚合类类型T被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:

  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument. 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成。
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list. 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T所有构造函数,参数列表由初始化列表的元素组成。

If the initializer list has no elements and T has a default constructor, the first phase is omitted. 如果初始化列表没有元素且T具有默认构造函数,则省略第一个阶段。 In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. 在copy-list-initialization中,如果选择了explicit构造函数,则初始化是错误的。

So the compiler will first try to create the vector using 因此编译器将首先尝试使用创建向量

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

As pointed out by user5389903 since you have a const std::size_t s and its value is within the range of an int it can convert {s} into a std::initializer_list<int> . 正如user5389903指出的那样 ,因为你有一个const std::size_t s并且它的值在int的范围内,所以它可以将{s}转换为std::initializer_list<int> now since we have a valid std::initializer_list the std::initializer_list constructor will be called. 既然我们有一个有效的std::initializer_list那么将调用std::initializer_list构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当double是常量时,为什么g ++ -Wconversion不会警告double转换为long int? - Why doesn't g++ -Wconversion warn about conversion of double to long int when double is constant? 为什么没有clang警告从double到int的隐式转换,但是从long到int时呢? - Why doesn't clang warn about implicit conversion from double to int, but do it when from long to int? 如果可能存在未定义的行为,为什么编译器不会警告您? - Why doesn't the compiler warn you if there is possible Undefined Behaviour? 为什么编译器不执行类型转换? - Why doesn't the compiler perform a type conversion? 无符号到有符号的转换 - unsigned to signed conversion 将本地引用返回到本地变量时,编译器为什么不警告“返回本地变量或临时地址”? - Why doesn't the compiler warn “returning address of local variable or temporary” when returning a local reference to a local variable? 为什么编译器不会在同一个翻译单元中警告ODR违规 - Why doesn't the compiler warn against ODR violations in the same translation unit 为什么编译器会警告在初始化列表中隐藏成员? - Why does the compiler warn about shadowing a member in initalization lists? 为什么编译器不抱怨将char添加到char *? - Why doesn't the compiler complain about adding char to char*? 为什么编译器不抱怨catch子句? - Why the compiler doesn't complain about the catch clauses?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM