0

私はJavaの出身で、コンテナの充填には思考が含まれていませんでした。私がc++で作業している今の私の問題は、関数スコープで宣言されたデータで関数のコンテナーを埋めると、エラーが発生する可能性があり、アクセスしたいときにデータが存在しなくなることです。問題に対処するチュートリアルが見つからなかったので、Javaの方法で、「new」で宣言されたポインターを取得するコンテナーのみを作成しました。しかし今、私は返還を余儀なくされています

std::list<Vertex<float> >

関数から、これは私がそのようなものをどのように埋めて返すかを学ぶための良いポイントかもしれないと思いました。これでしょうか

{
std::list<Vertex<float> > myList;
Vertex<float> v(0.0, 0.1, 0.2);
myList.push_back(v);
myList.push_back(Vertex<float>(1,0, 1.1, 1.2));
return myList;
}

実際にサンプル関数本体としては問題ありませんか?もしそうなら、なぜvはまだスコープ外に存在するのでしょうか?コンテナへの各挿入は、コピーも意味しますか?

4

2 に答える 2

1

そこでのすべての操作でコピーが作成されるため、これは「正常に」機能します。

  • myList.push_back(v);のコピーを作成して、のv可視性vが現在は無関係になるようにします。
  • return myList;リストのコピーを呼び出し元の関数に返すため、myListの表示は無関係になります。呼び出し元の関数は、スコープ内に保持するためにこのリストのコピーを作成する必要があります。そうしないと、この関数を呼び出す行の実行の最後にリストが破棄されます。

罰金が引用される理由は、コピーは通常高価だからです。あなたの場合、それらは非常に小さいので、無関係である可能性があり、多くの場合、それらは最適化されていない可能性がありますが、それでも覚えておくべきことがあります。

最適化の古いC++の方法は、値で返すのではなく、参照によってリストを渡し、それを使用してリストを作成することです。

void MakeMeAList(std::list<Vertex<float> >& aList){
    ....
}

std::list<Vertex<float> > aList;
MakeMeAList(aList);

@billzが示唆しているように、戻り値の最適化は、これが行われていなくてもコピーを最適化する必要があります。

新しいC++(c ++ 11)-
リストを作成する ためにを使用するemplace_backと、入力変数が使用されなくなる限り、コピーよりも効率的になります。(@Troyに感謝)

私のC++11は弱いです。移動セマンティクスがそれを最適化するので、値で返すことさえ大丈夫だとほぼ確信していますが、私は95%しか確信していません。

于 2013-01-14T02:34:29.027 に答える
1

Karthik の回答に追加すると、r 値参照 (C++0x 標準の一部) を実装する比較的新しいコンパイラを使用している場合、コピー操作の悪影響なしに、アプローチは完全に機能します。

r 値の簡単な紹介については、http://en.wikipedia.org/wiki/C%2B%2B11#Rvalue_references_and_move_constructorsをご覧ください。

右辺値参照が採用される前は、多くのコンパイラが、戻り値の最適化と呼ばれるものを通じて、コレクションを返す際の「コストのかかるコピー操作」を排除していたことに注意してください。ここでも Wiki に詳細があります: http://en.wikipedia.org/wiki/Return_value_optimization

Visual Studio 2005 (およびそれ以降) は RVO を実装しており、GCC にも同様の機能があると思います。つまり、引数を使用して値を返すよりも読みやすいコードは正しいアプローチであり、最新のコンパイラを使用している場合は非常にうまく機能するはずです。

于 2013-01-14T02:59:22.703 に答える