指针容器与对象容器 - 性能

时间:2009-11-11 22:45:56

标签: c++ performance pointers

我想知道比较/对比时性能是否有任何差异

A)在堆上分配对象,将指针放在容器中的那些对象上,在代码中的其他位置操作容器

例如:

std::list<SomeObject*> someList;

// Somewhere else in the code
SomeObject* foo = new SomeObject(param1, param2);
someList.push_back(foo);

// Somewhere else in the code
while (itr != someList.end())
{
    (*itr)->DoStuff();
    //...
}

B)创建一个对象,将其放入容器中,在代码中的其他位置操作该容器

例如:

std::list<SomeObject> someList;

// Somewhere else in the code
SomeObject newObject(param1, param2);
someList.push_back(newObject);

// Somewhere else in the code
while (itr != someList.end())
{
    itr->DoStuff();
    ...
}

假设指针都已正确解除分配且一切正常,我的问题是......

如果存在差异,会产生更好的性能,差异有多大?

5 个答案:

答案 0 :(得分:6)

插入对象而不是指向对象的指针会导致性能下降。

std::list以及其他std容器会复制您存储的参数(对于std::map,密钥和值都会被复制)。

由于您的someList是std :: list,因此以下行会复制您的对象:

Foo foo;
someList.push_back(foo);           // copy foo object

从列表中检索时,它将再次被复制。因此,与使用以下方式复制指针相比,您正在制作整个对象的副本:

Foo * foo = new Foo();
someList.push_back(foo);             // copy of foo*

您可以通过在Foo的构造函数,析构函数,复制构造函数中插入print语句来进行双重检查。

编辑:正如评论中所述,pop_front不会返回任何内容。您通常会使用front引用前元素,然后使用pop_front从列表中删除元素:

Foo * fooB = someList.front();    // copy of foo*
someList.pop_front();

OR

Foo fooB = someList.front();  // front() returns reference to element but if you
someList.pop_front();         // are going to pop it from list you need to keep a
                              // copy so Foo fooB = someList.front() makes a copy

答案 1 :(得分:3)

与大多数表演问题一样,这没有一个明确的答案。

首先,这取决于你对列表的确切做法。指针可能使更容易进行各种操作(如排序)。那是因为比较指针和交换指针可能比比较/交换SomeObject更快(当然,它取决于SomeObject的实现)。

另一方面,动态内存分配往往比在堆栈上分配更糟糕。因此,假设堆栈中有足够的内存用于所有对象,这是另一件需要考虑的事情。

最后,我个人会推荐我所得到的最好的建议:尝试猜测什么会表现更好是毫无意义的。以最有意义的方式编码(最容易实现/维护)。 如果且仅当* 您稍后发现存在性能问题时,请运行探查器并找出原因。很可能,大多数程序都不需要所有这些优化,这将成为一个没有实际意义的点。

答案 2 :(得分:1)

这取决于您如何使用列表。你只是用东西填充它,并进行查找,或者你是否定期插入和删除数据。没有指针,查找可能会略微加快,而使用指针添加和删除元素会更快。

答案 3 :(得分:0)

对于对象,假设没有任何复制构造函数和=运算符重载,它将成为成员复制(因此新对象创建和成员复制)。因此,使用指针是有效的std :: auto_ptr或boost的智能指针更好,但这超出了这个问题的范围。

如果仍然需要使用引用的对象语法。

答案 4 :(得分:0)

需要考虑的其他一些事项(您已经了解了STL容器的复制语义):

  • 您的对象是否真的小于指向它们的指针?如果您使用任何类型的智能指针,这会变得更加相关,因为那些指针往往更大。
  • 复制操作(经常?)优化,以便编译器使用memcpy()。特别是智能指针可能不适用。
  • 由指针引起的其他解除引用

我提到的所有事情都是微观优化的考虑因素,我甚至不鼓励考虑它们并与它们一起使用。另一方面:我的许多声明都需要验证,并会产生有趣的测试用例。随意对它们进行基准测试。