1

そのテストコードを検討してください。

#include <iostream>
using namespace std;

class Klass
{
public:
  Klass()
  {
    cout << "Klass()" << endl;
  }

  Klass(const Klass& right)
  {
    cout << "Klass(const Klass& right)" << endl;
  }
};

Klass create(Klass a)
{
  cout << "create(Klass a)" << endl;
  return a;
}

int main()
{
  const Klass result = create(Klass());
}

コンパイル:

g++ -O3 rvo.cpp   -o rvo

出力は次のとおりです。

$ ./rvo
Klass()
create(Klass a)
Klass(const Klass& right)

関数の戻り値とパラメーターのコピーを回避するために、コンパイラーがすべてのCOPYCTOR呼び出しを削除するためにRVOメカニズムを使用することを期待していましたcreate()。なぜそうではないのですか?

4

2 に答える 2

3

標準では、関数の引数として一時的なものを渡す場合にのみ、コピー省略が許可されます。

あなたが期待している 2 つのエリシオンは、以下の太字で示されています。

[C++11: 12.8/31]:特定の基準が満たされている場合、オブジェクトのコピー/移動コンストラクターおよび/またはデストラクタに副作用がある場合でも、実装はクラス オブジェクトのコピー/移動構築を省略できます。このような場合、実装は、省略されたコピー/移動操作のソースとターゲットを、同じオブジェクトを参照する 2 つの異なる方法として扱い、そのオブジェクトの破棄は、2 つのオブジェクトが削除されていた時間のうちの遅い方の時点で発生します。最適化なしで破壊されました。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。

  • クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv 非修飾型を持つ不揮発性自動オブジェクト (関数または catch-clause パラメーター以外) の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます
  • throw 式で、オペランドが非揮発性自動オブジェクト (関数または catch 節パラメーター以外) の名前であり、そのスコープが最も内側の try ブロック (存在する場合) の末尾を超えない場合。 )、オペランドから例外オブジェクトへのコピー/移動操作(15.1)は、自動オブジェクトを例外オブジェクトに直接構築することにより省略できます
  • 参照 (12.2) にバインドされていない一時クラス オブジェクトが同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、一時オブジェクトをターゲットに直接構築することにより、コピー/移動操作を省略できます。省略されたコピー/移動の
  • 例外ハンドラーの例外宣言 (条項 15) が、例外オブジェクト (15.1) と同じ型 (cv 修飾を除く) のオブジェクトを宣言する場合、例外宣言を次のように扱うことによって、コピー/移動操作を省略することができます。 exception-declaration によって宣言されたオブジェクトのコンストラクターとデストラクタの実行を除いて、プログラムの意味が変更されない場合は、例外オブジェクトのエイリアス。[..]

不揮発性の名前が関数パラメーターだったため、戻り値では発生しませんでした。

パラメータへの構築で発生しました。createそれ以外の場合は次のようになります。

Klass()
Klass(const Klass& right)
create(Klass a)
Klass(const Klass& right)
于 2012-02-15T13:03:14.460 に答える
2

表示されるコピーは、「create」関数の「return」ステートメントのコピーです。戻り値を直接構築することはできないため、RVO によって除去することはできません。「返品」をリクエストしました。ここではコピーが必要です。それなしでオブジェクトを返す方法はありません。

標準的な話では、[C++11: 12.8/31] の次の条件は満たされていません。

クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性自動オブジェクト(関数または catch-clauseパラメーター以外) の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます

理由については、これは恣意的なルールではありません。実装の観点からは理にかなっています。これは、関数パラメーターでは実行できないことです。

自動オブジェクトを関数の戻り値に直接構築する

関数パラメーターをコピーしています。関数に入る前にパラメーターが既に存在するため、インライン化せずにこのコピーを削除することはできません。したがって、代わりにそのオブジェクトを戻り値に直接構築することはできません。

于 2012-02-15T13:06:00.457 に答える