我正在测试推回对象与将对象指针推回到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变慢了..
为什么这个...... ??
答案 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获得相同的性能。