在STL容器中保存对象指针而不是对象本身更好吗?

16 浏览
0 Comments

在STL容器中保存对象指针而不是对象本身更好吗?

假设我有一个类A,并且我需要一个包含类A对象的vector。\n使用std::vector还是std::vector更好?\n我看过一些讲座提到,前者不需要定义复制构造函数和复制赋值运算符;而后者需要定义两者。这个说法正确吗?

0
0 Comments

这个问题的出现是因为在使用STL容器时,我们需要考虑是将对象本身存储在容器中,还是将对象的指针存储在容器中。这两种方法各有利弊,因此需要根据具体情况进行选择。

将指针存储在容器中可以提供更大的灵活性,因为我们不需要使用对象的操作符,或者可以使用具有副作用和/或高代价的操作符。容器本身会在最坏的情况下复制指针,而这种复制的代价是相当低的。此外,可以在同一继承层次结构中存储不同大小的对象(特别是如果它们具有虚方法)。

另一方面,将对象本身存储在容器中可以降低访问开销,因为您不需要每次访问元素时解引用指针。此外,它还将改善数据局部性(从而降低缓存未命中、页面未命中等),减少内存消耗和碎片化。

没有普遍适用的规则。对于经常读取而很少修改的容器,可能更适合直接将没有副作用的小对象存储在其中,而对于经常修改和调整大小的容器,可能更适合将具有昂贵副作用的构造函数和复制操作符的大对象存储在其他地方。

您必须考虑您的使用情况,并权衡每种方法的利弊。

0
0 Comments

在C++中,与许多其他现代语言不同,C++更适用于值类型。如果存储指针,就必须管理所得对象的生命周期。除非使用unique_ptr或类似的智能指针,否则语言无法帮助您管理。追踪对象丢失会导致内存泄漏,而在处理完对象后仍保留对它们的追踪会导致悬空引用/指针。这两种情况都是非常常见的错误。

如果存储值(或类似值类型),并且教会您的数据如何高效地移动自己,那么vector将在内存中连续存储它们。

在现代计算机上,CPU速度很快,而内存的速度非常慢。一台典型的计算机将拥有3级缓存,以尝试加快内存访问速度,但如果您的数据分散在内存中(因为使用了堆来存储对象),CPU几乎无法确定您将要访问的位置。

如果您的数据在一个连续的缓冲区中,不仅可以一次从内存中获取多个对象,而且CPU还能够猜测您将要访问的下一个内存块,并为您预取它。

所以简而言之,如果您的对象大小适中,请使用实际对象的vector副本。如果它们稍大一些,请将频繁访问的内容放在对象中,将不太频繁访问的大部分放在对象内的vector中,并编写高效的move语义。然后将对象本身存储在vector中。

但是也有一些例外情况。

首先,值类型的多态性很难处理,因此您最终会经常使用堆。

其次,某些对象的位置是其标识的一部分。向量会移动对象的位置,重新安置对象的成本可能不值得麻烦。

第三,性能通常并不重要。所以你做简单的事情。同时,值类型并不那么困难,尽管过早优化是一个坏主意,但过早地取消优化也是一个坏主意。学习如何处理值类型和连续向量是重要的。

最后,要学习零规则。零规则是指管理资源的对象应仔细编写其复制/移动/赋值/移动赋值/析构函数,以遵循值语义规则(或阻止)。然后使用这些资源管理对象的对象通常不需要真正编写它们的移动/复制/赋值/移动赋值/析构函数-它们可以留空、使用=default或类似的方式。

您不编写的代码往往比您编写的代码更少出错。

0