簡體   English   中英

C ++ 11中“return {}”語句的含義是什么?

[英]What does “return {}” statement mean in C++11?

這句話是什么?

return {};

在C ++ 11中指出,何時使用它而不是(比如說)

return NULL;

要么

return nullptr;

return {}; 表示“返回使用空list-initializer初始化的函數返回類型的對象”。 確切的行為取決於返回的對象的類型。

來自cppreference.com (因為OP標記為C ++ 11,我排除了C ++ 14和C ++ 17中的規則;請參閱該鏈接以獲取更多詳細信息):

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

    • 將std :: initializer_list作為唯一參數的所有構造函數,或作為第一個參數,如果其余參數具有默認值,將檢查所有構造函數,並通過重載決策與std :: initializer_list類型的單個參數進行匹配
    • 如果前一個階段沒有產生匹配,則T的所有構造函數都參與對由braced-init-list元素組成的參數集的重載解析,並限制只允許非縮小轉換。 如果此階段產生顯式構造函數作為復制列表初始化的最佳匹配,則編譯失敗(注意,在簡單的復制初始化中,根本不考慮顯式構造函數)。
  • 否則(如果T不是類類型),如果braced-init-list只有一個元素,並且T不是引用類型或者是與元素類型兼容的引用類型,則T是直接的 - 初始化(在直接列表初始化中)或復制初始化(在復制列表初始化中),但不允許縮小轉換。

  • 否則,如果T是與元素類型不兼容的引用類型。 (如果引用是非常量左值引用,則會失敗)
  • 否則,如果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;
}

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

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

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

這可能令人困惑:

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

這可能不是:

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

return {}; 表示{}返回值的初始值設定項 返回值使用空列表進行列表初始化。


以下是基於C ++標准中[stmt.return]的返回值的一些背景知識:

對於按值返回的函數(即返回類型不是引用而不是void ),有一個名為返回值的臨時對象。 此對象由return語句創建,其初始值設定項取決於return語句中的內容。

返回值一直存在,直到調用該函數的代碼中的完整表達式結束; 如果它有類類型,那么它的析構函數將運行,除非它的生命周期延長了調用者直接將引用綁定到它。

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


假設T是函數的返回類型,則注意return T{}; return {}不同:在前者中,創建臨時T{} ,然后從該臨時復制初始化返回值

如果T沒有可訪問的copy / move-constructor,則無法編譯,但return {}; 即使那些構造函數不存在,也會成功。 因此, return T{}; 可能會顯示復制構造函數等的副作用,雖然這是復制省略,因此可能不會。


下面簡要回顧一下C ++ 14中的列表初始化 (N4140 [dcl.init.list] / 3),其中初始化器是一個空列表:

  • 如果T是一個聚合,那么每個成員都是從它的大括號或初始化器中初始化的,如果它有一個,否則好像是{} (所以遞歸地應用這些步驟)。
  • 如果T是具有用戶提供的默認構造函數的類類型,則調用該構造函數。
  • 如果T是具有隱式定義的或= default ed默認構造函數的類類型,則對象將進行零初始化 ,然后調用默認構造函數。
  • 如果Tstd::initializer_list ,則返回值為空這樣的列表。
  • 否則(即T是非類型 - 返回類型不能是數組),返回值為零初始化。

這是方法返回類型的新實例的一種簡寫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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