【问题标题】:Containers vs Smart pointers in C++C ++中的容器与智能指针
【发布时间】:2019-07-09 12:46:26
【问题描述】:

如何在 std::containers(std::vectorstd::array)和指向数组的智能指针之间做出选择

我知道容器是内存管理的对象。它们是异常安全的,不会有任何内存泄漏,它们还为内存管理(push.back 等)提供了真正的功能,智能指针也是不会泄漏内存的指针,因为它们在不再需要它们时会删除它们(超出范围时就像 unique_ptr 一样)。可能在容器中每次创建它们都会产生开销。

我的问题是如何决定使用哪种方法以及为什么。

std::vector <unsigned char>myArray(3 * outputImageHight * outputImageWidth);

std::unique_ptr<unsigned char[]>myArray(new unsigned char[3 * outputImageHight * outputImageWidth]);

【问题讨论】:

  • 始终默认为容器,在 99.99% 的情况下它都是正确的。
  • 除非您测量性能下降,因为您有一些在原始unique_ptr 中不存在的东西。那就是 0.01%。
  • 请用文字代替图片。
  • @MatthieuBrucher 而性能下降是该程序的三大瓶颈。
  • 所以数组的智能指针只存在于 0.01% 的情况

标签: c++ containers smart-pointers


【解决方案1】:

我会使用向量。您的指针版本基本上没有对矢量进行任何改进,并且您失去了很多有用的功能。您很可能需要在某个时候测量大小并迭代您的数组,使用您免费获得的向量,而您需要自己为指针版本实现它;在这一点上,您可能只是使用了向量开始。

可能实例化向量会产生性能成本,但我怀疑它会成为大多数应用程序的瓶颈。如果您要创建如此多的向量而实例化它们会花费您的时间,那么您可能会更聪明地管理它们(池化内存、自定义向量分配器等)。如有疑问,请测量。

您可能需要使用unique_ptr&lt;&gt; 版本的一个示例可能是,如果您正在使用用C 编写的库,而您失去了数组的所有权。例如:

std::unique_ptr<unsigned char[]>myArray(
    new unsigned char[3 * outputImageHight * outputImageWidth]);

my_c_lib_data_t cLibData;
int result = my_c_lib_set_image(cLibData, myArray);

if (MYLIB_SUCCESS == result)
    // mylib successfully took ownership of the char array, so release the pointer.
    myArray.release();

如果您可以选择,请尽可能使用 C++ 风格的容器。

【讨论】:

  • 实际上我确实需要在数组上进行迭代,而且我确实需要测量大小并自己实际实现它。我也想过这个问题,但我的问题是,如果从来没有理由对数组使用智能指针,为什么还要添加它们?
  • @Aris - 好问题!我在我的答案中添加了一个额外的段落,其中涵盖了 unique_ptr 版本可能有用的示例。
【解决方案2】:

std::vector,主要是因为它更好地表示“连续内存中的项目序列”,它是它的默认表示,并且可以实现广泛的常见操作。

vector 具有移动语义,因此 std::unique_ptr 的好处是有限的。

如果你幸运的话,你的 STL 实现`提供小向量优化,跳过小尺寸的内存分配。
-- 编辑:我不知道SBO 显然被标准禁止 - 抱歉让您抱有希望,谢谢@KarlNicholl

如果需要指针语义,unique_ptr&lt;vector&lt;T&gt;&gt;shared_ptr&lt;vector&lt;T&gt;&gt; 是一个有效的选择,开销很小。

boost 确实引入了shared_array 等,更好地代表了您的第二个选择, 但我还没有看到他们获得多大的吸引力。

【讨论】:

  • 现在std::vector支持小向量优化吗?最后我知道这是不允许的,因为swap() 可能会使具有 SBO 向量实现的迭代器失效,这是不允许的(参见此处stackoverflow.com/a/8191356/52724)。也就是说,boost::container::small_vector 存在并且对于小缓冲区优化很有用。
【解决方案3】:

始终使用 STL 容器,除非您有充分的理由使用指针。原因是可靠性和可读性,IMO。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2011-06-14
    • 2011-08-12
    • 2019-06-30
    • 1970-01-01
    相关资源
    最近更新 更多