web-dev-qa-db-ja.com

C ++ 11での「return {}」ステートメントの意味

声明は何ですか

return {};

c ++ 11では、(たとえば)の代わりにそれを使用するタイミングを示します

return NULL;

または

return nullptr;
110
Pedia

return {};は、「空の list-initializer "で初期化された関数の戻り値型のオブジェクトを返す」ことを示します。正確な動作は、返されるオブジェクトのタイプによって異なります。

cppreference.com から(OPにはC++ 11のタグが付けられているため、C++ 14およびC++ 17のルールを除外しました。詳細についてはリンクを参照してください):

  • Braced-init-listが空で、Tがデフォルトのコンストラクターを持つクラス型である場合、値の初期化が実行されます。
  • それ以外の場合、Tが集約タイプの場合、集約の初期化が実行されます。
  • そうではなく、Tがstd :: initializer_listの特殊化である場合、Tオブジェクトは、コンテキストに応じて、braced-init-listから直接初期化またはコピー初期化されます。
  • それ以外の場合、2つのフェーズでTのコンストラクターが考慮されます。

    • Std :: initializer_listを唯一の引数として、または残りの引数にデフォルト値がある場合は最初の引数として取るすべてのコンストラクターが検査され、std :: initializer_list型の単一の引数に対するオーバーロード解決によって照合されます
    • 前の段階で一致が生成されない場合、Tのすべてのコンストラクターは、braced-init-listの要素で構成される引数セットに対するオーバーロード解決に参加します。ただし、非縮小変換のみが許可されます。この段階でcopy-list-initializationに最適な明示的コンストラクターが生成されると、コンパイルは失敗します(単純なcopy-initializationでは、明示的コンストラクターはまったく考慮されません)。
  • そうでない場合(Tがクラス型でない場合)、braced-init-listに要素が1つしかなく、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 NULLおよびreturn nullptrを使用する必要があります。

any_type* get_pointer() {
    return nullptr;
}

ただし、NULLは整数値(0)の単なるエイリアスであるため、C++ 11から非推奨になりましたが、nullptrは実際のポインター型です。

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

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

これはおそらく紛らわしいです:

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

これはおそらくそうではありません:

SomeObjectWithADefaultConstructor foo()
{
  return {};
  // equivalent to return SomeObjectWithADefaultConstructor {};
}
89
Richard Hodges

return {};は、{}戻り値の初期化子であることを意味します。戻り値は空の​​リストでリスト初期化されます。


C++標準の[stmt.return]に基づくreturn valueの背景を次に示します。

値によって返す関数(つまり、戻り値の型は参照ではなくvoidではありません)には、return valueという一時オブジェクトがあります。このオブジェクトはreturnステートメントによって作成され、その初期化子はreturnステートメントの内容に依存します。

戻り値は、関数を呼び出したコードの完全な式の終わりまで存続します。クラス型がある場合、呼び出し元が参照を直接バインドすることで有効期間が延長されない限り、デストラクタが実行されます。

戻り値は、2つの異なる方法で初期化できます。

  • return some_expression;-戻り値は copy-initialized from some_expression
  • return { possibly_empty_list };-戻り値は、リストから list-initialized です。

Tが関数の戻り値型であると仮定すると、return T{};return {}とは異なることに注意してください。前者では、一時的なT{}が作成され、戻り値は、その一時からコピー初期化されます。

Tにアクセス可能なコピー/移動コンストラクターがない場合、これはコンパイルに失敗しますが、return {};は、それらのコンストラクターが存在しなくても成功します。したがって、return T{};はコピーコンストラクタなどの副作用を示す場合がありますが、これはコピー省略コンテキストであるため、表示されない場合があります。


C++ 14(N4140 [dcl.init.list]/3)のlist-initializationの簡単な要約です。初期化子は空のリストです。

  • Tが集約の場合、各メンバーはbrace-or-equal-initializerがあればそれから初期化され、そうでなければ{}によるように初期化されます(したがって、これらの手順を再帰的に適用します)。
  • Tがユーザー提供のデフォルトコンストラクターを持つクラスタイプの場合、そのコンストラクターが呼び出されます。
  • Tが暗黙的に定義されたクラス型、または= defaultedデフォルトコンストラクターである場合、オブジェクトは zero-initialized であり、デフォルトコンストラクターが呼び出されます。
  • Tstd::initializer_listの場合、戻り値は空の​​そのようなリストです。
  • それ以外の場合(つまり、Tは非クラス型です-戻り値の型は配列にできません)、戻り値はゼロで初期化されます。
26
M.M

これは、メソッドの戻り値型の新しいインスタンスの一種の略記です。

3
Victor Mwenda