【问题标题】:Performance of std::vector<Test> vs std::vector<Test*>std::vector<Test> 与 std::vector<Test*> 的性能
【发布时间】:2012-06-30 21:24:13
【问题描述】:

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

例如:

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

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

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

换句话说:当我定义一个vector&lt;Test&gt;时,编译器会在内部创建一个vector&lt;Test*&gt;吗?

【问题讨论】:

    标签: performance pointers stl vector stdvector


    【解决方案1】:

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

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

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

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

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


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

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

    【讨论】:

    • 这听起来好像使用指针更快。我声称,至少对于许多常见的使用模式来说,相反就是这种情况:使用指针较慢,因为它增加了间接性和内存管理开销。 C++11 移动赋值使这一点更加真实,但它甚至在 C++03 中也成立。
    • 我编辑了我的问题。也许最后一行澄清了我在徘徊。
    • @Pietro 已更新我的答案以解决该问题并希望得到清除。
    • 康拉德鲁道夫,你能解释一下为什么指针会变慢吗?如果列表是 list 是否需要创建新的 Test 实例并在调用 push_back 时复制该值?谢谢
    【解决方案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 数组一样访问它是合法的),因此编译器实际上必须在内部将元素存储为数组,而不仅仅是存储指针。

    但请注意,数组指针只有在向量没有被重新分配时才有效(这通常只在大小增长到超出容量时才会发生)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 2020-09-22
      • 2018-06-06
      • 1970-01-01
      相关资源
      最近更新 更多