2015-09-29 84 views
1

我最近得到了在与该码的对接位:为什么编译器不会对未签名转换签名提出警告?

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

,而不是与一个大小为10初始化,这与初始化尺寸为1与一个元件10。但是,矢量有一个明确的构造函数,它需要一个std::size_t。随着所有关于“随处使用大括号”的宣传,我预计很多人都陷入了这个陷阱。如果编译器只是警告我们试图将size_t变成int,这可以避免。

为什么不要求编译器要做到这一点?

编辑:我原来的代码有const std::size_t s。显然没有我使用的编译器警告,除非我删除了const。这是一个错误?

+0

没有信息丢失 – valdo

+2

[未能这里编译](http://coliru.stacked-crooked.com/a/4e2010051a6bc5ff) – NathanOliver

+3

打开警戒线起来,用MSVS2015代码给了我“错误C2398:元素“ 1':从'size_t'转换为'int'需要缩小转换“和”警告C4267:'初始化':从'size_t'转换为'int',可能丢失数据“ – Blastfurnace

回答

2

不,它是不是一个错误。参见[dcl.init.list] N3337/7:

收缩转换是隐式转换

...

  • 从整数型或无作用域枚举类型为整数不能代表除了 原始类型的所有值,其中所述源是一个常量表达式和后 转换将装配到目标类型,并产生当转换回原始类型原始 值的实际值类型。

因此,代码是有效的,只要是sconst

1

,而不是与一个大小为10初始化,这与初始化尺寸为1与一个元件10

首先初始化列表是gready:

§13.3.1.7[过来。 match.list]/P1:

当非聚合类类型T的对象是列表初始化 (8.5.4),过载第S选在两个阶段的构造:

  • 最初,候选功能是类T的初始化列表构造器(8.5.4)和参数列表包括 初始化列表作为单个参数。
  • 如果没有找到可行的初始化列表构造函数,重载决议再次进行,其中候选功能是类T和参数列表的所有 的构造由初始化列表的 元素。

如果初始化列表没有任何元素和T具有默认 构造中,省略了第一阶段。在复制列表初始化中,如果选择explicit构造函数,则 初始化为 不合格。

因此,编译器将首先尝试通过user5389903创建使用

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

由于pointed out的载体,因为你有一个const std::size_t s,其价值是int的范围内,它可以转换{s}std::initializer_list<int> 。现在,因为我们有一个有效的std::initializer_list构造函数std::initializer_list将被调用。

相关问题