2016-11-26 42 views
1

我注意到當使用Apple的clang-release(703.0.31)時,通過push_back方法將[signed] int推送到std::vector<unsigned int>方法會引發關於隱式符號轉換的警告。考慮到警告標誌,我對此感到滿意,但感到驚訝的是用emplace_back方法替換它並沒有產生警告。`push_back`與`emplace_back`簽署警告

我用godbolt測試了這個,而叮噹3.9.0表現出相同的行爲。在任何情況下,gcc 6.2都不會產生警告。由於隱式符號轉換診斷不是(AFAIK)所需的行爲,所以我會毫不猶豫地將其稱爲一個錯誤,但我很好奇,如果我忽略了一些解釋(或複雜化)展示行爲的邊界情況。

+0

你的問題是什麼?這是爲什麼'push_back'時'emplace_back'不會產生警告?或者,爲什麼鏗鏘會首先發出警告? – Rakete1111

+3

這就是爲什麼你通常不想使用進位語義。 Emplacement是關於顯式轉換的,這意味着*你承諾可以根據你的args和預期的結果構建元素。如果您有現有值,請使用插入,而不是放置。例如:'std :: vector time_to_missile_launch; time_to_missile_launch.emplace(15);' –

+1

(缺少)警告的第二個原因是,使用push_back時,轉換髮生在呼叫站點,而使用emplace_back時,它發生在系統頭部內部,這通常會禁用警告。 –

回答

4

是這樣的區別:

signed a = 0; 
unsigned b = a; 

而且這樣的:

unsigned b = unsigned(a); 

後者是一種典型的方式來阻止發生這樣的警告(其他方式將是一個鑄)。

,當你調用emplace_back()這是完全一樣的 - 這種方法的整個要點是結構一個value_type從(你的情況未簽名)給定值。

同樣,如果您有:

struct Foo { explicit Foo(int x) {} }; 

然後,你可以這樣做:

std::vector<Foo> v; 
v.emplace_back(1); 

但不是這樣的:

v.push_back(1); 

綜上所述,emplace_back()意義不「push_back()但效率更高。」相反,它是「在容器中使用這些參數構造一個value_type」。

+0

*「另一種方式是演員」*好,'無符號(a)'*是*演員,不是嗎? – user2079303