7

私はstd::vector多くのことを利用するプログラムを扱っています。また、何十億もの割り当て/割り当て解除が行われており、できるだけ多くの割り当てを回避しようとしています。私は C++ に比較的慣れていないので、ベクトルを使用する場合 (要素を追加する場合など) に行われる割り当てに関していくつか質問があります。私は Win7 64 ビット マシンを使用しています。プログラムは 32 ビットで、現在のバージョンの MinGW コンパイラを使用しています。

次の場合、つまり、ベクトルがコピーされ、参照として渡された場合にどうなるかを知りたいです...

1.

std::vector<T> fillVector() {
    std::vector<T> returnVector;
    ...
    return returnVector;
}

std::vector<T> myVector = fillVector();

2.

 std::vector<T>& fillVector() {
    std::vector<T>* returnVector = new std::vector<T>;
    ...
    return (*returnVector);
}

std::vector<T> myVector = fillVector();

3.

std::vector<T>* fillVector() {
    std::vector<T>* returnVector = new std::vector<T>;
    ...
    return returnVector;
}

std::vector<T>* myVector = fillVector();

そして、次の異なる操作:

4.

std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;

5.

std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);

myFunction/changes inの引数を in に変更myVectorしたくないと仮定してもmyFunction、プログラムの残りの部分に影響はありません。

6.

void myFunction(std::vector<T> myParam) {
   ...
}

std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);

7。

void myFunction(std::vector<T>& myParam) {
   ...
}

std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);

私の理解が正しければ、最速のオプション (コピーを作成して渡す代わりに参照を渡すことを意味します) は 2/3、5、および 7 です。間違っている場合は修正してください!

4

2 に答える 2

7

1.

std::vector<T> fillVector() {
    std::vector<T> returnVector;
    ...
    return returnVector;
}

std::vector<T> myVector = fillVector();

これで問題ありません。はvalue によってvector返されますが、コピー コンストラクターの呼び出しは、(名前付き) 戻り値の最適化の下で、ほとんどのコンパイラ (少なくとも最適化がオンになっている場合) によって省略されます。

さらに、C++11 では、ムーブ セマンティクスにより、コピー コンストラクターではなく、ムーブ コンストラクターが呼び出されることが保証されます。コピー コンストラクターは、高価なコピーを生成することなく、返されたベクターの中身を盗むだけです。

2.

 std::vector<T>& fillVector() {
    std::vector<T>* returnVector = new std::vector<T>;
    ...
    return (*returnVector);
}

std::vector<T> myVector = fillVector();

これをしないでください。動的割り当ての不要なオーバーヘッドに加えて、返されたオブジェクトの割り当てを解除する必要があることを覚えておく必要があります。手動のメモリ管理を避け、1 を優先します。

3.

std::vector<T>* fillVector() {
    std::vector<T>* returnVector = new std::vector<T>;
    ...
    return returnVector;
}

std::vector<T>* myVector = fillVector();

同上。手動のメモリ管理は避けてください。

4.

std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;

これは概念的に異なる操作です。ここでコピーを作成したいのですが、正しくやっているようです。C++11 では、内容をコピーするのではなく転送std::vector<T> myVector = std::move(myVector1)するだけでよい場合に使用できます。myVector1

5.

std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);

上記と同じように、コピーを作成したいのですが、ベクトルを不必要に動的に割り当てています。これもまた、その有効期間を手動で処理することを余儀なくされますが、これは悪いことであり、エラーが発生しやすくなります。これをしないでください。

6.

void myFunction(std::vector<T> myParam) {
   ...
}

std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);

ここでは、値渡しをmyVectorしています。これが最適化できるかどうかmyFunctionは、その引数で何を行うことが想定されているかによって異なります。変更する必要がありますか? その場合、関数から戻った後にこれらの変更を表示しますか? はいの場合、値渡しは正しく、オブジェクトを取得したい場合を除きmyVector、オブジェクトを最適化する方法はありません。その場合、C++ 11 では、関数に渡すときにオブジェクトを移動できます。これにより、高価で不要なコピーが回避されます。

7。

void myFunction(std::vector<T>& myParam) {
   ...
}

std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);

これは参照渡しであり、関数から戻った後にmyFunctiononの副作用が見られれば問題ありません。myVectorそれが正しいかどうかは、一般的には言えません。アプリケーションの特定のロジックに依存します。

于 2013-02-27T19:15:59.407 に答える
1

最も高速で最も慣用的なのはオプション 1 です。両方のコピー ( fromreturnVectorから戻り値と from 戻り値からmyVector) は、ほぼ確実にコンパイラによって省略されます。コピー省略は、不要なコピーを削除することを含む、コンパイラが行う最適化です。ここでは、両方のコピーは不要であり、 のstd::vector代わりに が直接構築されmyVectorます。

実際、コンパイラでコピー省略の最適化を無効にしても、C++11 では両方のコピーが実際には移動になります。移動にstd::vectorはいくつかの割り当てが必要で、非常に迅速です。fillVector()式が右辺値式であるため、1 つ目は特別な規則によって移動と見なされ、2 つ目は移動と見なされます。

于 2013-02-27T19:10:14.803 に答える