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

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

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

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


当前回答

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

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

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

其他回答

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

初始大小

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[]>不是容器

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

出于二进制兼容性的考虑,您需要结构只包含一个指针。 你需要使用一个API来返回用new[]分配的内存 例如,您的公司或项目有一个禁止使用std::vector的一般规则,以防止粗心的程序员不小心引入副本 您希望防止粗心的程序员在这种情况下意外地引入副本。

有一个普遍的规则,c++容器比使用指针滚动自己的容器更受欢迎。这是一个普遍规律;它有例外。有更多的;这些只是例子。

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

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。

在一些Windows Win32 API调用中可以找到一个常见的模式,其中使用std::unique_ptr<T[]>可以派上用场,例如,当你调用一些Win32 API(将在该缓冲区中写入一些数据)时,不知道输出缓冲区应该有多大:

// Buffer dynamically allocated by the caller, and filled by some Win32 API function.
// (Allocation will be made inside the 'while' loop below.)
std::unique_ptr<BYTE[]> buffer;

// Buffer length, in bytes.
// Initialize with some initial length that you expect to succeed at the first API call.
UINT32 bufferLength = /* ... */;

LONG returnCode = ERROR_INSUFFICIENT_BUFFER;
while (returnCode == ERROR_INSUFFICIENT_BUFFER)
{
    // Allocate buffer of specified length
    buffer.reset( BYTE[bufferLength] );
    //        
    // Or, in C++14, could use make_unique() instead, e.g.
    //
    // buffer = std::make_unique<BYTE[]>(bufferLength);
    //

    //
    // Call some Win32 API.
    //
    // If the size of the buffer (stored in 'bufferLength') is not big enough,
    // the API will return ERROR_INSUFFICIENT_BUFFER, and the required size
    // in the [in, out] parameter 'bufferLength'.
    // In that case, there will be another try in the next loop iteration
    // (with the allocation of a bigger buffer).
    //
    // Else, we'll exit the while loop body, and there will be either a failure
    // different from ERROR_INSUFFICIENT_BUFFER, or the call will be successful
    // and the required information will be available in the buffer.
    //
    returnCode = ::SomeApiCall(inParam1, inParam2, inParam3, 
                               &bufferLength, // size of output buffer
                               buffer.get(),  // output buffer pointer
                               &outParam1, &outParam2);
}

if (Failed(returnCode))
{
    // Handle failure, or throw exception, etc.
    ...
}

// All right!
// Do some processing with the returned information...
...

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