2015-09-29 89 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將被調用。

相關問題