1

重複の可能性:
コピー省略と戻り値の最適化とは?
コピーコンストラクターが呼び出されないのはなぜですか

次のコードで、gcc と clang の両方が A クラスのコピー コンストラクターを 1 回も呼び出さないのはなぜですか (デストラクタが 1 回だけ呼び出されるため、作成されるオブジェクトは 1 つだけです)。

class A
{
public:
  explicit A()
  {
    std::cout << "A()" << std::endl;
  }
  A(const A& toCp)
  {
    std::cout << "A(const A&)" << std::endl;
  }
  ~A()
  {
    std::cout << "~A()" << std::endl;
  }
  A& operator=(const A& toCp)
  {
    std::cout << "A::operator=" << std::endl;
  }
};

A fun()
{
  A x;
  std::cout << "fun" << std::endl;
  return x;
}

int main()
{
  A u = fun();
  return 0;
}

このコードの出力は次のとおりです。

A()
fun
~A()

コピーコンストラクターは2回呼び出す必要があると思いました(1回は値を返すため、もう1回は行で)A u = fun(7);

このコードには -O0 を指定して gcc と clang を使用しました。

何か案は?

4

1 に答える 1

2

コンパイラは、関数の戻り値のコピー (または移動) を回避するためにコピー省略fun()を使用します。これは標準的で簡単な最適化であり、ほとんど常に呼び出されます (コンパイラとその最適化設定によって異なります)。省略されたコピー(または移動)コンストラクターに副作用があったとしても(あなたの場合のように、stdoutに書き込む場合)、コンパイラーはこれを行う場合があります。

noteコピー省略はinline関数に限定されませんが、関数定義が別のコンパイル単位に存在する場合でも使用されます。

于 2013-01-04T14:21:58.167 に答える