0

rvalueと lvalueについて数時間を費やしました。これが私が理解していることです

int main()
{
  //.....
  Foo foo = Bar1();
  foo = Bar2();
  //......
}  

Foo Bar1()
{
  //Do something including create foo
  return foo;
}

Foo& Bar2()
{
  //Do something including create foo
  return foo;
}

c++03 ではBar1()、返されたオブジェクトを (return の直前に) コピーし、コピーされたオブジェクトのアドレスを返します。破棄されようとしているオブジェクトの無駄なコピーを実行します。Bar2()関数内で作成されたオブジェクトを返します。

C++11 ではBar1()Bar2()本質的に同等です (またBar2()、c++03 と同等です)。

そうですか?そうでない場合は、詳しく説明してください。

4

5 に答える 5

6

それらは同じではありません。Bar2()両方の基準でUBです。参照によってスタック上に作成されたオブジェクトを返すことはできません。

C++03 ではBar1()RVO を利用でき、何もコピーされません。C++11 ではBar1()、RVO を使用するか、RVO が使用できない場合はムーブ コンストラクターを使用します。

于 2012-12-06T22:40:33.600 に答える
1

Bar2()は C++ 2003 でも C++ 2011 でもコピーを作成しません。Bar1()のコピーはfooC++ 2003 と C++ 2011 の両方で作成されます。右辺値参照の使用は、実際に右辺値がある場合、または左辺値が離れようとしていて、それは返されています。

もちろん、この例はたまたま未定義の動作になりfooますfoofooつまり、返されたときに何が意図されているかを述べていないため、例が台無しになっているようです。各関数にローカル変数があると仮定するとfooBar2()両方の標準に従って未定義の動作であり、Bar1()多少異なります。

  • のムーブ コンストラクターがある場合Foo、C++ 2011 ではムーブ コンストラクターが使用され、C++ 2003 ではコピー コンストラクターが使用される場合があります。
  • 移動コンストラクターとコピー コンストラクターのどちらが使用されるかは、関数の残りの部分とコンパイラによってreturn異なりBar1()ますfoo
于 2012-12-06T22:50:26.127 に答える
1

右辺値と左辺値の概念は、古い C++ から C++11 まで変わりませんでした。あなたが「C++03」と表現することは、起こるべきことです。場合によっては、コンパイラの最適化によって、不要なコピー (不要なコピー コンストラクターの呼び出しを含む) の数を減らすことができますが、それ以外は同じです。

変更されたのは、C++11 で右辺値参照 ( T&&) の概念が導入されたことです。

Google で検索できる記事がいくつかあります。たとえば、こちら:

http://thbecker.net/articles/rvalue_references/section_01.html

于 2012-12-06T22:40:53.333 に答える
0

Bar2()は、関数内で作成されたオブジェクトを返します。

それは明らかに間違っています。あるオブジェクトへの参照Bar2()を返します。(注:オブジェクトが内部のスタックに作成された場合はUBになります)。Bar2()

c ++ 11では、Bar1()とBar2()は基本的に同等です(c ++ 03のBar2()とも同等です)。

C++11では意味は同じです。あなたが本当に興味を持っているのは、移動のセマンティクスです。

Foo Bar3()
{
  //Do something
  return std::move(foo);
}

これはコピーコンストラクターを実行しませんが、移動コンストラクターを実行します。これにより、リソースの消費がはるかに少なくなります。

于 2012-12-06T22:43:25.217 に答える
0

この記事はあなたにとって興味深いかもしれません:スピードが欲しいですか?値渡し。

C ++ 03ではBar1()、オブジェクトをコピーする場合があります(ただし、これはいわゆるコピーの省略に最適化されています。リンクを参照してください)。

C ++ 11では、基本的に何も変更されていません。コンパイラーは、FooのコピーコンストラクターまたはFooの移動コンストラクターを呼び出すか、コピーの省略を行うことができます。ただし、C ++ 03でもコピーが省略されるためBar1()、C++11およびC++03でも同じようになります。

Bar2()参照のみを返します。C++11でも違いはありません。参照を返すことは重要な場合があります。ローカル値の場合foo、すでに破棄された変数への参照が返されますが、これへの参照は返されません。

于 2012-12-06T22:46:36.303 に答える