2016-09-14 148 views
95

這句話是什麼在C++ 11中,「return {}」語句的含義是什麼?

return {}; 

在C++ 11指示,以及何時使用它,而不是(說)

return NULL; 

return nullptr; 
+54

它返回函數返回類型的默認構造實例。 –

+0

或者簡單的'return;'沒有價值? – i486

+0

不,正如討論所揭示的那樣,如果你的函數應該返回一些東西(即不是void返回類型)並且你只寫了'return;'另一方面'return {};'是有效的你有一個返回類型。 – Pedia

回答

93

return {};表示「返回一個空list-initializer初始化函數的返回類型的對象」。確切的行爲取決於返回的對象的類型。

cppreference.com(因爲OP被標記C++ 11,I排除C++ 14和C++ 17的規則是指該鏈接的其他細節):

  • 如果braced-init-list是空的,而T是具有默認構造函數的類類型,則執行值初始化。
  • 否則,如果T是聚合類型,則執行聚合初始化。
  • 否則,如果T是std :: initializer_list的特化,則T對象將根據上下文從braced-init-list直接初始化或複製初始化。
  • 否則,T的構造都認爲,在兩個階段:

    • 所有構造函數採取的std :: initializer_list作爲唯一的參數,或者作爲第一個參數,如果其餘的參數有默認值,是通過重載決議匹配std :: initializer_list
    • 如果前一階段沒有產生匹配,T的所有構造函數都會參與重載解析,這是針對由braced-init-list,限制只允許非縮小轉換。如果這個階段產生一個顯式構造函數作爲複製列表初始化的最佳匹配,編譯失敗(注意,在簡單的複製初始化中,根本不考慮顯式構造函數)。
  • 否則(如果T是不是類型)中,如果支撐-INIT列表僅具有一個元素,或者T是不是引用類型或引用類型是與類型兼容元素T直接初始化(在直接列表初始化中)或複製初始化(在複製列表初始化中),除了不允許縮小轉換之外。

  • 否則,如果T是與元素的類型不兼容的引用類型。 (如果引用是非const左值引用,則失敗)
  • 否則,如果braced-init-list沒有元素,則T進行了值初始化。

之前C++ 11,返回一個std::string的功能,你會寫:

std::string get_string() { 
    return std::string(); 
} 

使用C++ 11的支柱語法,你不需要重複類型:

std::string get_string() { 
    return {}; // an empty string is returned 
} 

return NULLreturn nullptr時,應使用該函數返回一個指針類型:

any_type* get_pointer() { 
    return nullptr; 
} 

然而,NULL是因爲C++ 11推薦使用,因爲它只是一個別名爲整數值(0),而nullptr是一個真正的指針類型:

int get_int() { 
    return NULL; // will compile, NULL is an integer 
} 

int get_int() { 
    return nullptr; // error: nullptr is not an integer 
} 
87

這可能是令人困惑:

int foo() 
{ 
    return {}; // honestly, just return 0 - it's clearer 
} 

這可能不是:

SomeObjectWithADefaultConstructor foo() 
{ 
    return {}; 
    // equivalent to return SomeObjectWithADefaultConstructor {}; 
} 
+9

因此,如果返回類型沒有默認構造函數,那麼這是一個編譯時錯誤,是否正確? – Pedia

+1

@KarimPedia它當然應該是。 –

+9

如果返回類型是一個沒有_non-explicit_默認構造函數且不是聚合的類,那麼這是一個編譯錯誤。 – Oktalist

24

return {};意味着{}是初始值設定爲返回值。返回值是用空列表進行列表初始化的。


這裏是關於返回值一些背景下,根據[stmt.return]在C++標準:

對於由值返回一個函數(即,返回類型不是一個參考而不是void),有一個臨時對象稱爲返回值。此對象由return語句創建,其初始化程序取決於返回語句中的內容。

返回值一直存在,直到調用該函數的代碼中的全表達式結束;如果它具有類類型,那麼它的析構函數將運行,除非它的生命週期由調用者直接綁定一個引用來擴展。

返回值可以通過兩種不同的方式進行初始化:


假設T是函數的返回類型,然後記下return T{};return {}不同:前者,臨時T{}被創建,然後返回值是複製初始化從臨時。

如果T沒有可訪問的複製/移動構造函數,這將無法編譯,但return {};將成功,即使這些構造函數不存在。因此,return T{};可能會顯示副本構造函數等的副作用,儘管這是一個複製elision上下文,因此它可能不會。


這裏的列表初始化採用簡短的回顧一下C++ 14(N4140 [dcl.init.list]/3),其中,所述初始化是一個空列表:

  • 如果T是一個聚合,然後每個成員從它的括號或等號初始化程序初始化,如果它有一個,否則就像{}(所以遞歸地應用這些步驟)。
  • 如果T是一個具有用戶提供的默認構造函數的類類型,則調用該構造函數。
  • 如果T是一個具有隱式定義或缺省構造函數的類類型,則該對象爲zero-initialized,然後調用默認構造函數。
  • 如果Tstd::initializer_list,則返回值是一個空的此類列表。
  • 否則(即T是非類類型 - 返回類型不能是數組),返回值是零初始化的。
+0

Aggregate init首先出現,它用'{}'遞歸地初始化每個成員,這可能是也可能不是value-init。 –

+0

@ T.C。對,我去了cppreference,但忽略了一個「直到C++ 14」 –

3

對於方法返回類型的新實例來說,這是一種簡短的手段。

相關問題