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

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

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

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


当前回答

与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());
}

其他回答

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

这里有权衡,您可以选择与您想要的匹配的解决方案。我能想到的是:

初始大小

vector和unique_ptr<T[]>允许在运行时指定大小 数组只允许在编译时指定大小

调整

array和unique_ptr<T[]>不允许调整大小 向量是

存储

vector和unique_ptr<T[]>将数据存储在对象之外(通常在堆上) 数组将数据直接存储在对象中

复制

数组和向量允许复制 unique_ptr<T[]>不允许复制

交换/移动

vector和unique_ptr<T[]>有O(1)次交换和移动操作 数组有O(n)次交换和移动操作,其中n是数组中元素的数量

指针/引用/迭代器失效

array ensures pointers, references and iterators will never be invalidated while the object is live, even on swap() unique_ptr<T[]> has no iterators; pointers and references are only invalidated by swap() while the object is live. (After swapping, pointers point into to the array that you swapped with, so they're still "valid" in that sense.) vector may invalidate pointers, references and iterators on any reallocation (and provides some guarantees that reallocation can only happen on certain operations).

概念和算法的兼容性

array和vector都是容器 unique_ptr<T[]>不是容器

我不得不承认,对于基于策略的设计来说,这似乎是一个重构的机会。

简而言之:它是迄今为止最节省内存的。

A std::string comes with a pointer, a length, and a "short-string-optimization" buffer. But my situation is I need to store a string that is almost always empty, in a structure that I have hundreds of thousands of. In C, I would just use char *, and it would be null most of the time. Which works for C++, too, except that a char * has no destructor, and doesn't know to delete itself. By contrast, a std::unique_ptr<char[]> will delete itself when it goes out of scope. An empty std::string takes up 32 bytes, but an empty std::unique_ptr<char[]> takes up 8 bytes, that is, exactly the size of its pointer.

最大的缺点是,每次我想知道字符串的长度,我必须调用strlen。

您可能使用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<T[]>的另一个原因是,到目前为止还没有在响应中提到:它允许向前声明数组元素类型。

当您希望最小化头文件中的链式#include语句(以优化构建性能)时,这非常有用。

例如:

myclass.h:

class ALargeAndComplicatedClassWithLotsOfDependencies;

class MyClass {
   ...
private:
   std::unique_ptr<ALargeAndComplicatedClassWithLotsOfDependencies[]> m_InternalArray;
};

myclass.cpp:

#include "myclass.h"
#include "ALargeAndComplicatedClassWithLotsOfDependencies.h"

// MyClass implementation goes here

使用上面的代码结构,任何人都可以#include " MyClass .h"并使用MyClass,而不必包括MyClass::m_InternalArray所要求的内部实现依赖。

如果m_InternalArray被声明为std::array< alargeandcomplatedclasswithlotsofdependencies >,或者std::vector<…> -结果将尝试使用不完整的类型,这是一个编译时错误。