Std::unique_ptr支持数组,例如:
std::unique_ptr<int[]> p(new int[10]);
但这是必要的吗?可能使用std::vector或std::array更方便。
你觉得这个结构有什么用处吗?
Std::unique_ptr支持数组,例如:
std::unique_ptr<int[]> p(new int[10]);
但这是必要的吗?可能使用std::vector或std::array更方便。
你觉得这个结构有什么用处吗?
当前回答
医生:这是穷人的性病。
让我们把std::unique_ptr<T[]>看作一个容器。实际上,由于缺少size字段,不能直接作为容器使用,它在标准库中可用的容器的“参数空间”中占据了一个点,而这个点不被其他合适的容器共享——即使在混合中添加Boost也不行。
如果你看看我对广泛可用的类向量/连续容器的比较,并寻找与std::unique_ptr相同的特性:
堆上的分配 容量在编译时不固定 在建造后不能改变容量(没有完全清理集装箱)
你会发现除了std::dynarray,没有其他容器提供所有这些;但它实际上不在标准库中——它本应被纳入c++ 14,但最终被拒绝了。
我不仅仅是在猜测。甚至在《SO》中,人们也偶尔这样描述事物;参见@KerrekSB 2013年对这个问题的回答。
其他回答
与std::vector和std::array相反,std::unique_ptr可以拥有一个NULL指针。 这在使用期望数组或NULL的C api时非常方便:
void legacy_func(const int *array_or_null);
void some_func() {
std::unique_ptr<int[]> ptr;
if (some_condition) {
ptr.reset(new int[10]);
}
legacy_func(ptr.get());
}
您可能使用unique_ptr的一个原因是,如果您不想支付初始化数组值的运行时成本。
std::vector<char> vec(1000000); // allocates AND value-initializes 1000000 chars
std::unique_ptr<char[]> p(new char[1000000]); // allocates storage for 1000000 chars
// C++20 version:
auto p = std::make_unique_for_overwrite<char[]>(1000000);
std::vector构造函数和std::vector::resize()将对t进行值初始化,但new和std::make_unique_for_overwrite将默认初始化它们,这对于PODs来说意味着什么都不做。
参见c++ 11中的值初始化对象和std::vector构造函数
注意,vector::reserve在这里不是一个替代方案:在std::vector::reserve之后访问原始指针是安全的吗?
这和C程序员选择malloc而不是calloc的原因是一样的。
我遇到了一个情况,我必须使用std::unique_ptr<bool[]>,它位于HDF5库(用于高效二进制数据存储的库,在科学中使用很多)中。一些编译器(在我的例子中是Visual Studio 2015)提供std::vector<bool>的压缩(通过在每个字节中使用8个bool),这对于HDF5之类的东西来说是一个灾难,它不关心这种压缩。对于std::vector<bool>, HDF5最终会因为压缩而读取垃圾。
猜猜谁在那里进行救援,在std::vector不起作用的情况下,我需要干净地分配一个动态数组?: -)
为了回答人们认为你“必须”使用vector而不是unique_ptr,我在GPU上的CUDA编程中有一个案例,当你在Device中分配内存时,你必须使用一个指针数组(使用cudaMalloc)。 然后,当在Host中检索该数据时,必须再次寻找指针,unique_ptr可以很容易地处理指针。 将double*转换为vector<double>的额外成本是不必要的,并且会导致性能损失。
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会说些什么呢?