2

在非 POD 数据类型的 std::vector 中,对象向量和指向对象的(智能)指针向量之间有区别吗?我的意思是编译器对这些数据结构的实现有所不同。

例如:

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

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

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

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

4

2 回答 2

2

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

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

对于像您这样的简单对象Test,复制将如此之快以至于无关紧要。

此外,在 C++11 中,移动可以避免在不需要时创建额外的副本。

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


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

答案在低于 C++ 级别时变得复杂得多。由于整个程序无法放入寄存器,因此当然必须涉及指针。不过,我对那个低级别的了解还不够多,无法详细说明。

于 2012-06-29T10:35:12.437 回答
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 回答