std :: vector <test> vs std :: vector <test *> </test *> </test>的性能

时间:2012-06-29 10:32:42

标签: performance pointers stl vector stdvector

在非POD数据类型的std :: vector中,对象向量和对象(智能)指针向量之间是否存在差异?我的意思是编译器对这些数据结构的实现存在差异。

E.g:

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

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

vt和vpt之间可能没有性能差异吗?

换句话说:当我定义vector<Test>时,编译器会在内部创建vector<Test*>吗?

2 个答案:

答案 0 :(得分:2)

通常,无论向量中存储的类型是什么,都可以复制其实例。这意味着如果要存储std :: string,将复制std :: string的实例。

例如,当您将Type推入向量时,Type实例将被复制到向量内部的实例中。复制指针会很便宜,但正如Konrad Rudolph在评论中指出的那样,这不应该是你唯一考虑的事情。

对于像Test这样的简单对象,复制速度会非常快,无关紧要。

此外,使用C ++ 11,移动可以避免在没有必要的情况下创建额外的副本。

简而言之:指针将被更快地复制,但复制并不是唯一重要的事情。当问题成为问题时(或者情况需要它),我会首先担心可维护的逻辑代码和性能。


关于内部指针向量的问题,不,向量被实现为在必要时定期调整大小的数组。你可以在网上找到GNU的libc ++矢量实现。

答案在低于C ++级别时变得更加复杂。指针当然必须参与,因为整个程序不适合寄存器。虽然我不太了解那个低级别的内容,但我还不太了解。

答案 1 :(得分: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数组一样访问它是合法的),因此编译器有效地必须在内部将元素存储为数组,并且可能不仅存储指针。

但请注意,只要矢量未重新分配(通常仅在大小超出容量时才会发生),数组指针才有效。