2

非PODデータ型のstd::vectorでは、オブジェクトのベクトルとオブジェクトへの(スマート)ポインタのベクトルに違いはありますか? コンパイラによるこれらのデータ構造の実装の違いを意味します。

例えば:

class Test {
   std::string s;
   Test *other;
};

std::vector<Test> vt;
std::vector<Test*> vpt;

vt と vpt の間にパフォーマンスの違いはありませんか?

言い換えれば、 を定義するvector<Test>と、コンパイラは内部的に を作成しvector<Test*>ますか?

4

2 に答える 2

2

言い換えれば、ベクトルを定義すると、コンパイラは内部的にベクトルを作成しますか?

いいえ、これは C++ 標準では許可されていません。次のコードは正当な C++ です。

vector<Test> vt;
Test t1; t1.s = "1"; t1.other = NULL;
Test t2; t2.s = "1"; t2.other = NULL;
vt.push_back(t1);
vt.push_back(t2);
Test* pt = &vt[0];
pt++;
Test q = *pt; // q now equal to Test(2)

言い換えれば、ベクトルは配列に「減衰」するため (C 配列のようにアクセスすることは正当です)、コンパイラは事実上配列として要素を内部的に格納する必要があり、ポインターを格納するだけではない場合があります。

ただし、配列ポインターは、ベクターが再割り当てされない限り有効であることに注意してください (通常、サイズが容量を超えて大きくなった場合にのみ発生します)。

于 2012-07-25T20:21:42.280 に答える
2

一般に、ベクトルに格納されている型が何であれ、そのインスタンスをコピーできます。これは、std::string を格納している場合、std::string のインスタンスがコピーされることを意味します。

たとえば、Type をベクターにプッシュすると、Type インスタンスはベクター内に格納されたインスタンスにコピーされます。ポインターのコピーは安価ですが、Konrad Rudolph がコメントで指摘したように、これだけを考慮する必要はありません。

のような単純なオブジェクトの場合Test、コピーは非常に高速になるため問題ありません。

さらに、C++11 では、移動することで、不要な場合に余分なコピーを作成することを回避できます。

要するに、ポインターはより高速にコピーされますが、重要なのはコピーだけではありません。私は保守可能な論理コードを最初に心配し、それが問題になったとき (または状況がそれを必要とするとき) にパフォーマンスを心配します。


内部ポインタ ベクトルに関する質問については、いいえ、ベクトルは必要に応じて定期的にサイズ変更される配列として実装されます。GNU の libc++ 実装の vector をオンラインで見つけることができます。

C++ レベルよりも低いレベルでは、答えはさらに複雑になります。プログラム全体がレジスターに収まらないため、ポインターはもちろん関与する必要があります。私はそのレベルの低さについて詳しく説明するのに十分な知識がありません。

于 2012-06-29T10:35:12.437 に答える