3

私はこの機能を持っているとしましょう:

template <class A>
inline A f()
{
  A const r(/* a very complex and expensive construction */);

  return r;
}

変数は移動できないr constので、を宣言するのは良い考えですか? const戻り値は ではないことに注意してくださいconst。私が取り組んでいる問題は、それはr本当にそうですが、そのconstように宣言するのは良い考えではないかもしれません. それでも修飾子は、コンパイラがより良いコードを生成するのに役立つはずです。

4

2 に答える 2

7

ここに示されているように、NRVO は行rによって暗示されたのコピーを省略します。return r;

#include <iostream>

struct A {
  const char* name;
  A( const char* name_ ):name(name_) { std::cout << "created " << name << "\n"; }
  A(A const&){ std::cout << "copied " << name << "\n"; }
  A(A &&){ std::cout << "moved " << name << "\n"; }
};

A f() {
  std::cout << "start of f()\n";
  A const r("bob");
  std::cout << "body of f()\n";
  return r;
}

int main() {
  A x = f();
}

また、コピーインmainも省略されます。

NRVO と RVO を他の方法でブロックすると (たとえば-fno-elide-constructors、GCC でコンパイルするときにフラグを使用するなど)、オブジェクトがdconstの代わりにコピーされる可能性があります。からコピー コンストラクターを削除すると、moveこれを確認できます。A

#include <iostream>

struct A {
  const char* name;
  A( const char* name_ ):name(name_) { std::cout << "created " << name << "\n"; }
  //A(A const&){ std::cout << "copied " << name << "\n"; }
  A(A &&){ std::cout << "moved " << name << "\n"; }
};

A f() {
  std::cout << "start of f()\n";
  A const r("bob");
  std::cout << "body of f()\n";
  return r;
}

int main() {
  A x = f();
}

コードはコンパイルされなくなります。NRVO が発生する限り、コピー コンストラクターは実行されませんが、その存在はconstローカル変数によって必要とされます。

現在、NRVO には、問題の関数のすべての実行パスに沿って返される単一の変数など、いくつかのことが必要です。「中止」して を実行するreturn A()と、NRVO がブロックされ、constローカル変数が突然コピーを強制しますすべての返品サイト。

于 2013-08-26T02:45:40.160 に答える
1

class Aがあなたの管理下にあり、移動によってオブジェクトを返したい場合はconst、次のことができます

mutable bool resources_were_stolen = false;

const移動コンストラクターでそれをtrueに設定します

A(const A&& other) { ...; other.resources_were_stolen = true; }
~A() { if (!resources_were_stolen) ... }

実際には、デストラクタはおそらく、オブジェクトが構築と破壊の際に - 性をif (resources_were_stolen) some_unique_ptr.release();失うという事実を利用して になるでしょう。const

于 2013-08-26T02:54:42.443 に答える