1. ホーム
  2. c++

[解決済み] C++11のデフォルトはpass-by-valueが妥当か?

2022-05-16 10:04:27

質問

伝統的なC++では、関数やメソッドに値を渡すことは大きなオブジェクトでは遅く、一般に嫌われることです。代わりに、C++ プログラマーは参照を渡す傾向があり、これは高速ですが、所有権や特にメモリ管理 (オブジェクトがヒープで割り当てられている場合) に関するあらゆる種類の複雑な問題を引き起こします。

C++11 では、Rvalue 参照と移動コンストラクタがあり、大きなオブジェクト(たとえば std::vector のような)大きなオブジェクトを実装することができ、関数への値の受け渡しが安価になります。

のような型のインスタンスは値で渡すのがデフォルトであるということでしょうか? std::vectorstd::string ? カスタムオブジェクトの場合はどうでしょうか?新しいベストプラクティスは何ですか?

どのように解決するのですか?

それは、合理的なデフォルトの もし は、本文の中にコピーを作成する必要があります。これは、Dave Abrahams が が提唱している :

ガイドライン 関数の引数をコピーしてはいけません。代わりに、値で渡して、コンパイラにコピーをさせる。

コードでは、これをするなということです。

void foo(T const& t)
{
    auto copy = t;
    // ...
}

が、こうする。

void foo(T t)
{
    // ...
}

これは、呼び出し側が foo のように

T lval;
foo(lval); // copy from lvalue
foo(T {}); // (potential) move from prvalue
foo(std::move(lval)); // (potential) move from xvalue

となり、最小限の作業しか行われません。リファレンスで同じことをするには、2つのオーバーロードが必要です。 void foo(T const&);void foo(T&&); .

それを踏まえて、今度は自分の評価済みコンストラクタをこのように書いてみました。

class T {
    U u;
    V v;
public:
    T(U u, V v)
        : u(std::move(u))
        , v(std::move(v))
    {}
};

それ以外の場合、参照渡しで const への参照渡しはまだ合理的です。