4

stl コンテナを返すファクトリ関数があります。

const std::vector<int> f(...) {
    std::vector<int> retval;
    return retval;
}

次のようにstlインスタンスを定義しても問題ないと思います(エラーなし):

const std::vector<int> stl_instance(f(...));

しかし、そうするのは効率的ですか?

一時的な stl オブジェクトは に直接割り当てられていstl_instanceますか?

4

2 に答える 2

5

const 右辺値を返すことは、C++11 のアンチパターンです。まず、非 const 右辺値を返すことを検討してください。

std::vector<int> f(int n) 
{ 
    return std::vector<int>(n); 
}

int main() 
{ 
    std::vector<int> v; 
    v = f(3); 
} 

C++98/03 では、このコードは少なくとも 2 回ヒープに移動します。

  1. f の内部にベクトルを作成するには (RVO が適用される場合)
  2. f のリターンから v に代入します。

コンパイラが RVO を適用しない場合、3 つのヒープ割り当てが得られます。

C++11 では、1 つのヒープ割り当てのみを取得します: 内にベクトルを作成しますf。これは、RVO に関係なく発生します。その理由は、すべての STL コンテナーには、署名を持つムーブ コンストラクターとムーブ代入演算子があるためです。

vector( vector&& other );
vector& operator=( vector&& other );

右辺値参照&&は、リソースを作成関数内から目的地に直接移動します。ただし、コードには署名があります

const std::vector<int> f(int n) 
{ 
    return std::vector<int>(n); 
}

T&& (つまり、move コンストラクターと代入演算子の引数) は const rvalue パラメーター (つまり、関数の戻り値) にバインドされないため、move セマンティクスを無効にします。これにより、効率的にコードが C++98/03 で実行されるようになります (つまり、2 つまたは 3 つのヒープ割り当てで)。

于 2013-01-10T10:39:17.907 に答える
1

それは罰金で合法的な法典です。コンパイラーは、コピーの省略を通じて
必要な最適化を処理します(可能な場合)。

一時的なf(...)ものは、少なくとも式が終了するまで存続することが保証されています。stl_instance(f(...))式は、正確には、からの戻りの直後に終了することに注意してください;呼び出しの最後のセミコロン)。したがって、それは完全に有効です。

C ++03標準§12.2/3:

一時オブジェクトは、それらが作成されたポイントを(字句的に)含む完全式(1.9)を評価する最後のステップとして破棄されます。

于 2013-01-10T04:52:45.723 に答える