7

C++11 標準では、コピー省略の条件が満たされた場合 ( §12.8/31)、実装はreturned ローカル左辺値変数と関数パラメーターを最初に右辺値として扱い (移動)、オーバーロードの解決が成功しない場合は次のように処理する必要があると述べています。その後、それを左辺値 (コピー) として扱います。

§12.8 [class.copy] p32

コピー操作の省略の基準が満たされているか、ソース オブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値によって指定されているという事実を除いて満たされる場合、コピーのコンストラクターを選択するためのオーバーロードの解決は次のとおりです。オブジェクトが rvalue によって指定されたかのように最初に実行されます。オーバーロードの解決が失敗した場合、または選択されたコンストラクターの最初のパラメーターの型がオブジェクトの型 (おそらく cv 修飾) への右辺値参照でない場合、オブジェクトを左辺値と見なしてオーバーロードの解決が再度実行されます。[注:この 2 段階のオーバーロード解決は、コピーの省略が発生するかどうかに関係なく実行する必要があります。省略が実行されない場合に呼び出されるコンストラクターを決定し、呼び出しが省略された場合でも、選択されたコンストラクターにアクセスできる必要があります。—終わりのメモ]

これにはメンバー サブオブジェクトも含まれますか? 次のスニペットでテストしました。

#include <iostream>

struct traced{
  traced(){ std::cout << "default ctor\n"; }
  traced(traced const&){ std::cout << "copy ctor\n"; }
  traced(traced&&){ std::cout << "move ctor\n"; }
};

struct X{
  traced t;
};

traced f(){
  X x;
  return x.t;
}

int main(){
  traced t = f();
}

Ideone での実例。 また、GCC 4.7 ToT も Clang 3.1 ToT も「move ctor」を表示しないため、標準にはメンバー サブオブジェクトが含まれていないと思われます。

私は何かを見落としましたか?私のテストコードは壊れていますか? 出力がそのままになる正確な原因は何ですか?

4

1 に答える 1

6

サブオブジェクトを返すとき、その構築を省略できません。次のように考えてください。移動とコピーの省略は、基本的に、最終的に移動またはコピーされる場所にオブジェクトを構築することになります。適切なスペースが確保されるため、これは完全なオブジェクトに対して機能します。囲んでいるオブジェクトを構築するため、サブオブジェクトでは機能しません。これがサブオブジェクトと同じサイズであっても、つまり十分なスペースがある場合でも、囲んでいるオブジェクトは破壊され、サブオブジェクトに奇妙なことをする可能性があります。

事実上、これは主語の構成を省略できないことを意味します。

于 2012-02-07T20:16:08.883 に答える