Std::unique_ptr支持数组,例如:

std::unique_ptr<int[]> p(new int[10]);

但这是必要的吗?可能使用std::vector或std::array更方便。

你觉得这个结构有什么用处吗?


当前回答

Scott Meyers在《Effective Modern c++》中这样说

对于数组来说,是否存在std::unique_ptr应该只对你的智力感兴趣,因为std::array, Std::vector, Std::string实际上总是比原始数组更好的数据结构选择。关于我能想到的唯一情况,当std::unique_ptr<T[]>有意义时,当你使用一个类似c的API,返回一个原始指针指向你假定拥有的堆数组时。

我认为Charles Salvia的答案是相关的:std::unique_ptr<T[]>是初始化一个在编译时不知道大小的空数组的唯一方法。对于使用std::unique_ptr<T[]>的动机,Scott Meyers会说些什么呢?

其他回答

std::vector可以被复制,而unique_ptr<int[]>允许表示数组的唯一所有权。另一方面,Std::array要求在编译时确定大小,这在某些情况下可能是不可能的。

为了回答人们认为你“必须”使用vector而不是unique_ptr,我在GPU上的CUDA编程中有一个案例,当你在Device中分配内存时,你必须使用一个指针数组(使用cudaMalloc)。 然后,当在Host中检索该数据时,必须再次寻找指针,unique_ptr可以很容易地处理指针。 将double*转换为vector<double>的额外成本是不必要的,并且会导致性能损失。

医生:这是穷人的性病。

让我们把std::unique_ptr<T[]>看作一个容器。实际上,由于缺少size字段,不能直接作为容器使用,它在标准库中可用的容器的“参数空间”中占据了一个点,而这个点不被其他合适的容器共享——即使在混合中添加Boost也不行。

如果你看看我对广泛可用的类向量/连续容器的比较,并寻找与std::unique_ptr相同的特性:

堆上的分配 容量在编译时不固定 在建造后不能改变容量(没有完全清理集装箱)

你会发现除了std::dynarray,没有其他容器提供所有这些;但它实际上不在标准库中——它本应被纳入c++ 14,但最终被拒绝了。

我不仅仅是在猜测。甚至在《SO》中,人们也偶尔这样描述事物;参见@KerrekSB 2013年对这个问题的回答。

我对公认答案的精神再怎么反对也不为过。“最后的手段”?远非如此!

在我看来,与C语言和其他类似语言相比,c++最强大的特性之一是能够表达约束,以便在编译时检查它们,并防止意外误用。因此,在设计结构时,要问问自己它应该允许哪些操作。应该禁止所有其他用途,最好能够静态地(在编译时)实现这些限制,以免误用导致编译失败。

因此,当需要一个数组时,以下问题的答案指定了它的行为: 1. 它的大小是a)在运行时动态的,还是b)静态的,但只在运行时知道,还是c)静态的,在编译时知道? 2. 数组是否可以分配到堆栈上?

根据这些答案,我认为这是这种数组的最佳数据结构:

       Dynamic     |   Runtime static   |         Static
Stack std::vector      unique_ptr<T[]>          std::array
Heap  std::vector      unique_ptr<T[]>     unique_ptr<std::array>

是的,我认为unique_ptr<std::array>也应该被考虑,这两个都不是最后的工具。想想什么最适合你的算法。

所有这些都通过指向数据数组的原始指针(vector.data() / array.data() / uniquePtr.get())与普通C api兼容。

P. S. Apart from the above considerations, there's also one of ownership: std::array and std::vector have value semantics (have native support for copying and passing by value), while unique_ptr<T[]> can only be moved (enforces single ownership). Either can be useful in different scenarios. On the contrary, plain static arrays (int[N]) and plain dynamic arrays (new int[10]) offer neither and thus should be avoided if possible - which should be possible in the vast majority of cases. If that wasn't enough, plain dynamic arrays also offer no way to query their size - extra opportunity for memory corruptions and security holes.

有些人无法奢侈地使用std::vector,即使是使用分配器。有些人需要一个动态大小的数组,所以std::array已经失效。有些人从已知返回数组的代码中获取数组;这段代码不会被重写为返回一个向量或其他东西。

通过允许unique_ptr<T[]>,您可以满足这些需求。

简而言之,您可以在需要时使用unique_ptr<T[]>。当其他选择都不适合你的时候。这是最后的手段。