簡體   English   中英

將'='添加到初始化列表之間是否有任何細微差別?

[英]Is there any subtle difference between prepending '=' to initializer lists?

這兩種在C ++ 11中初始化變量的方法之間有什么細微的差別嗎?

  1. vector<double> v { 0.0, 1.1, 2.2, 3.3 };

  2. vector<double> v = { 0.0, 1.1, 2.2, 3.3 };

后者可以用於與第一個相同的所有情況嗎?

Stroustrup在TCPL4ED中聲稱第一種方式是唯一可以在每個上下文中使用的方法,因此推薦它。 后來,他似乎暗示第二個只是寫第一個的另一種方式。

1。

vector<double> v { 0.0, 1.1, 2.2, 3.3 };

直接列表初始化 這意味着它是使用構造函數初始化列表初始化的。

構造函數:

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

2。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM