![](/img/trans.png)
[英]Difference between std::vector and std::array initializer lists
[英]Is there any subtle difference between prepending '=' to initializer lists?
這兩種在C ++ 11中初始化變量的方法之間有什么細微的差別嗎?
vector<double> v { 0.0, 1.1, 2.2, 3.3 };
vector<double> v = { 0.0, 1.1, 2.2, 3.3 };
后者可以用於與第一個相同的所有情況嗎?
Stroustrup在TCPL4ED中聲稱第一種方式是唯一可以在每個上下文中使用的方法,因此推薦它。 后來,他似乎暗示第二個只是寫第一個的另一種方式。
vector<double> v { 0.0, 1.1, 2.2, 3.3 };
是直接列表初始化 。 這意味着它是使用構造函數初始化列表初始化的。
構造函數:
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
vector<double> v = { 0.0, 1.1, 2.2, 3.3 };
是復制列表初始化 。
標准很清楚:
8.5.4列表初始化[dcl.init.list]
列表初始化是從braced-init-list初始化對象或引用。 這樣的初始化程序稱為初始化程序列表,列表的逗號分隔的初始化程序子句稱為初始化程序列表的元素。 初始化列表可以為空。 列表初始化可以在直接初始化或copyinitialization上下文中進行; 直接初始化上下文中的列表初始化稱為直接列表初始化,復制初始化上下文中的列表初始化稱為復制列表初始化。 [注意:可以使用列表初始化:
- 作為變量定義中的初始化器
[...]
示例:
std::complex<double> z{1,2}; [...] std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };
對於兩者之間的差異,我們應該進一步:
13.3.1.7按列表初始化初始化[over.match.list]
- 對於直接列表初始化 ,候選函數是類T的所有構造函數。
- 對於復制列表初始化 ,候選函數是T的所有構造函數。 但是,如果選擇了
explicit
構造函數,則初始化是錯誤的。 [注意:此限制僅適用於此初始化是重載解析的最終結果的一部分 - 結束注釋]
統一初始化的目的是(部分) 消除這兩種結構之間的差異。 確保它們具有相同的功能。
可悲的是,他們失敗了。 直接列表初始化(即: T t{...}
)和復制列表初始化(即: T t = {...}
)之間只有一個區別 。 您不需要復制/移動構造函數進行復制列表初始化(盡管名稱); 第8.5.4節沒有將其列為要求。 沒有一個臨時建造的概念可能會被遺棄。 他們有相同的行為, 除了 :
如果選擇explicit
構造函數,則復制列表初始化將失敗。 這是唯一的區別。
很難從規范中引用一個引用,因為只有3個提到復制列表初始化是什么。 一個是在8.5.4中,它定義了復制列表初始化是列表初始化的一種形式,另一個說明返回一個braced-init-list使用復制列表初始化。 13.3.1.7中的最后一個,它說明了上述異常:
在copy-list-initialization中,如果選擇了
explicit
構造函數,則初始化是錯誤的。
這是唯一的區別。
我想到的一個區別是,即使構造函數被聲明為explicit
,第二種形式也可以使用,而第二種形式則不然。 抱歉,但@Timothy Shields和@Tomek錯了,兩個語句都是直接初始化,而不是復制初始化。
我想這與普通構造函數的情況類似(即不使用初始化程序列表)。 第一個選擇是使用(在這種情況下)構造函數采用初始化列表構造函數的構造。 另一個選擇是使用初始化列表構造函數創建的臨時選項,然后該變量由該復制構造。 臨時然后消失。 請注意,后者通常會跳過臨時和復制銷毀,因為(N)RVO會啟動,但后者要求您的類在定義時具有可訪問的復制構造函數。 至少這是我記得的C ++ 03,它可能在C ++ 11中有所改變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.