C ++ Vector:push_back Objects vs push_back指针性能

时间:2014-07-22 20:16:53

标签: c++ pointers vector

我正在测试推回对象将对象指针推回到C ++中的Vector之间的性能差异。

我已经阅读过Stackoverflow和其他文章,你应该避免推回指针,除非你必须这样做......

但是,我意识到推回Pointers有很大的性能提升,

这是我跑的简单测试:

tstart = chrono::system_clock::now();

vector<MyObject> VectorOfObjects;
for (int i=0; i<10000; i++) {
    MyObject x("test");
    VectorOfObjects.push_back(x);
}

tend = chrono::system_clock::now();
tt = tend-tstart;
cout << "Pushback Object: " << tt.count()*1000 << " Milliseconds\n" << endl;




tstart = chrono::system_clock::now();

vector<MyObject *> VectorOfPointers;
for (int i=0; i<10000; i++) {
    VectorOfPointers.push_back(new MyObject("test"));
}

tend = chrono::system_clock::now();
tt = tend-tstart;
cout << "Pushback Pointers: " << tt.count()*1000 << " Milliseconds\n" << endl;


结果实际上非常令人惊讶:

Pushback Objects:  989 Milliseconds
Pushback Pointers: 280 Milliseconds


正如您所看到的,推回指针比推回物体快3~4倍!这是一个巨大的性能差异,特别是在处理大量数据时。

所以我的问题是:为什么不使用指针矢量?

Stackoverflow上关于类似问题的几乎所有帖子的答案都说避免指针的矢量..

我知道内存泄漏可能是一个问题,但我们总是可以使用智能指针,甚至手动删除破坏指针并不困难..

我也对这种性能差异的原因感到好奇。

由于


更新

实际上我在ideone上进行了测试....在这里,推回对象更快!!!

在Visual Studio中,推回对象让Wayyy变慢了..

为什么这个...... ??

3 个答案:

答案 0 :(得分:3)

公平地说,当你的代码measuring时,你应考虑释放所有这些指针。示例代码读作:

#include <chrono>
#include <string>
#include <iostream>
#include <functional>
#include <vector>

using namespace std;

// 1. A way to easily measure elapsed time -------------------
template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F>
    static typename TimeT::rep execution(F const &func)
    {
        auto start = std::chrono::system_clock::now();
        func();
        auto duration = std::chrono::duration_cast< TimeT>(
            std::chrono::system_clock::now() - start);
        return duration.count();
    }
};
// -----------------------------------------------------------


// 2. MyObject -----------------------------------------------
struct MyObject {
    string mem;
    MyObject(const char *text) : mem(text) {};
};
// -----------------------------------------------------------


int main() 
{
    vector<MyObject> VectorOfObjects;
    vector<MyObject *> VectorOfPointers;

    cout << "Pushback Object: " << measure<>::execution([&]()
    {
        for (int i = 0; i < 100000; i++) {
            MyObject x("test");
            VectorOfObjects.push_back(x);
        }
    }) << endl;


    cout << "Pushback Pointers: " << measure<>::execution([&]()
    {
        for (int i = 0; i < 100000; i++) 
            VectorOfPointers.push_back(new MyObject("test"));
        for (auto &item : VectorOfPointers) 
            delete item;
    }) << endl;

    return 0;
}

以及使用

编译时
  

g ++ -std = c ++ 11 -O3 -march = native -Wall -pedantic

结果是(我在for循环中使用了+1个数量级):

  

推回对象:20

     

推回指针:32


  • 如果您使用

      

    VectorOfObjects.emplace_back( “测试”);

    VectorOfObjects修改的持续时间将降至18

  • 如果你preallocated两个载体

    vector<MyObject> VectorOfObjects;
    VectorOfObjects.reserve(100000);
    
    vector<MyObject *> VectorOfPointers;
    VectorOfPointers.reserve(100000);
    

    结果将是17-34(对象的向量)

  • 如果您use a vector of unique pointers则结果相似

    vector<unique_ptr<MyObject>> VectorOfPointers;
    

    请注意,我正在限制向量的范围,以明确说明智能指针的销毁

  • 其他选择包括提升pointer containers,在这种情况下,相关数据结构将为pointer vector

答案 1 :(得分:2)

我更喜欢使用与常规指针相对的共享指针,而且我总是在可以的时候使用它们。

在处理变化很多的向量时,我使用带向量的共享指针。

在处理向量时应避免使用常规指针,因为它们需要手动破坏并且只会导致内存泄漏。

所以回答你的问题......

查看shared_ptr库并使用这些,而这里是一个链接http://www.cplusplus.com/reference/memory/shared_ptr/

希望这能回答你的问题

答案 2 :(得分:2)

编写示例代码的方式肯定存在内存泄漏问题。同意你可以通过删除来解决这个问题。

可以做到,但这只是麻烦。如果你处理内存泄漏等问题,那很好。

这里的性能根本问题是有正在制作的对象的副本。您创建一个对象。将其添加到矢量时。它创建一个新对象并使用复制构造函数复制您的对象。

C ++ 11通过引入emplace_back()改善了这种情况。因此,如果您使用的是C ++ 11,则可以通过使用emplace获得相同的性能。