【问题标题】:Can a std::array<T, N> release its data?std::array<T, N> 可以发布其数据吗?
【发布时间】:2016-06-28 16:03:35
【问题描述】:

unique_ptr 及其release 方法为例,该方法返回指向托管对象的指针并释放所有权
有没有办法释放 std::array 的底层数组的所有权?


好的,可以使用std::unique_ptr 而不是std::array,仅此而已。无论如何,后者有一些不错的功能,例如有时很有用的size 成员方法。

【问题讨论】:

  • 听起来像std::unique_ptr&lt;std::array&lt;...&gt;&gt; 会起作用。 std::array 不会选择数据所在的位置。
  • @chris 是的,不要认为这是一个现实世界的问题。我知道那里会起作用。我只是想知道是否有办法发布这些数据。我发现自己在说好吧,它会很有用,仅此而已。 :-)
  • 这似乎是一个更笼统的问题;你能在对象超出范围之前从对象中“拯救”一个成员吗?

标签: c++ arrays c++14


【解决方案1】:

有没有办法释放 std::array 底层数组的所有权?

没有。 std::array 只是原始数组的包装器。它可以重新分配,但这实际上是对数组中所有元素的复制操作。目标数组不指向源数组。

您还应该注意std::arraystd::unique_ptr&lt;type[]&gt; 的不同之处在于std::array 的大小必须在编译时知道,而std::unique_ptr&lt;type[]&gt; 的大小可以在运行时设置。 std::unique_ptr&lt;type[]&gt; 真正做的只是包装一个 type * name = new type[some_size]

【讨论】:

  • 请注意,如果想要保留std::array 的“好特性”,编写一个由std::unique_ptr&lt;type[]&gt; buffersize_t size 组成的包装类是很简单的,其中成员为@ 987654331@、endemptysize,当然还有release。基本上没有动态调整大小的灯光std::vector
  • @KABoissonneault 那仍然是聚合类型吗?
  • 我猜不是,我不想暴露包装器的size,它在构造上应该是正确的。
  • 虽然上述包装器可以有一个std::initializer_list&lt;type&gt; 构造函数,使它看起来像一个聚合类型,就像std::array。包装器将在内部分配拥有的缓冲区,并根据需要release
  • @KABoissonneault 可以。为您提供两全其美的体验。
【解决方案2】:

不,std::array 只是对原生数组的简单包装,因此它位于堆栈上,并且无法释放其内容,除非在内容自动从堆栈中弹出时超出范围

您应该考虑改用std::vector。由于您已经在处理堆上的数组。然后,您可以将std::move 向量转换为另一个向量以“转移”内容的所有权。例如

another_vec = std::move(old_vec); // now another_vec has the contents

注意如果你使用unique_ptr,你得到的数组是在堆上而不是在栈上!因此,您最好使用std::vector 及其data() 函数。但我不完全确定您的用例。

另一个注意事项在考虑使用 std::array 时另一件不太明显的事情是该类型是重量级对象,这意味着常规的右值优化可能 不能以最佳方式工作,因为移动不像vector 那样简单

【讨论】:

  • 虽然,std::vector 也不能“释放”其内部数据。
  • @user2079303 是的,你可以(至少以非保证的方式,这意味着实现优化了实际版本,这可能比你想要的要好)。看看std::vector::shrink_to_fit
  • 我认为您误解了“release 方法返回指向托管对象并释放所有权”的含义。 shrink_to_fit 什么都不做。 如果它重新分配给一个缩小的数组,原来的内存被销毁,而不是“释放”并返回给调用者。
  • @user2079303 没有 C++17 提案吗?我希望它被接受
  • @Curious 你可能应该建议一个答案,它有一个release,它返回一个指向内部缓冲区的指针
【解决方案3】:

«释放» std::array 基本上意味着调用析构函数并将内存用于其他用途。

您可以通过使用标准库中的 std::*::destroy 功能或显式调用析构函数来显式销毁显式构造的 std::array。

这是您通常想要避免的事情,除非您在没有其他选择的情况下实现非常基本的数据结构。一个用例是,如果您想控制何时以及如何构造和销毁全局数组,而无需通过指针进行间接寻址。

C++17 可能会提供新功能 destroy_at, destroy and destroy_n 显式销毁对象。

另请参阅C++ FAQ on destructors

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 2017-05-14
    • 2017-10-01
    • 1970-01-01
    相关资源
    最近更新 更多