C++ 什么时候应该使用智能指针来保存数组?

C++ 什么时候应该使用智能指针来保存数组?,c++,c++11,C++,C++11,我看到许多答案建议使用智能指针在内存中保存动态分配的数组。我的观点一直是,如果已知大小,则应将其包装在std::array中,同样,如果大小未知(即,通过将智能指针的指针类型设置为未知绑定的数组,并reset(),稍后将其重置),则应使用std::vector。事实上,我一直都是这样做的 例如,最近我看到一个答案使用了std::unique\u ptr p(new int[5])。这似乎类似于构造一个std::array,因为大小是已知的。此外,附加的好处是std::array静态分配其数组,并

我看到许多答案建议使用智能指针在内存中保存动态分配的数组。我的观点一直是,如果已知大小,则应将其包装在
std::array
中,同样,如果大小未知(即,通过将智能指针的指针类型设置为未知绑定的数组,并
reset()
,稍后将其重置),则应使用
std::vector
。事实上,我一直都是这样做的

例如,最近我看到一个答案使用了
std::unique\u ptr p(new int[5])
。这似乎类似于构造一个
std::array
,因为大小是已知的。此外,附加的好处是
std::array
静态分配其数组,并包含类似数组的特性,如大小、迭代器等


那么,与使用其他专门为此目的而设计的标准容器相比,使用智能指针来保存数组的原因是什么呢?

当您知道运行时的时间时,可以使用指向数组的唯一指针,但它不会改变,这保证了您将只为这些对象分配空间,而不会再为其他对象分配空间。对于向量,您可以在内部分配更多空间,这是实现定义的,但为了有良好的插入摊销时间,它通常在每次增长向量时分配至少两倍的所需空间,因为它需要复制。

首先,
unique\u ptr
不需要静态大小-它可以是
unique\u ptr

此外,额外的好处是std::array静态分配 它的数组

这并不能严格保证是一种利益。考虑一下,如果我有一个10兆字节的数组,那它就要炸毁我的栈。
一般来说,当人们希望数组大小在创建时固定,但能够变异成员时,他们会选择这种方法。请注意,对于
std::vector
,只能同时生成元素和
vector
常量,或者两者都不能。您不能只生成向量而不生成元素
const

std::vector
std::array
之间进行简单的权衡:“大小总是一样吗?”

然后,“我是否需要智能指针”的决定对于任何其他类型都是相同的。是否要将其作为共享对象传递?使用
std::shared\u ptr
。我想在不复制的情况下传递一个大对象吗?使用
std::unique\u ptr


假设您有一个2048缓冲区,您希望在程序中传递它,但不会引入很多副本。您可以使用
std::shared\u ptr

正如您所说,
std::array
是一个静态数组。如果在堆栈上声明
std::array
,则实际数组位于堆栈上。而
std::unique_ptr(new int[5])
将实际数组放在堆上。对于小型阵列来说,这似乎不是一个很大的区别,但对于大型阵列来说,这是一个很大的区别。仅仅因为数组的长度是固定的,并不意味着它应该总是在堆栈上。它取决于数组的大小和可用堆栈空间的大小。在堆栈上放置大型数组有引发堆栈溢出错误的风险。在堆上放置大型数组不会抛出该错误(除非堆栈已满,因此分配数组后无法构建
unique_ptr
),但如果堆/memmgr已满,抛出内存不足错误的风险较小,但是,在构建
Unique\ptr
之前,就会发生这种情况。

数组的智能指针就是智能指针。因此,您应该在适当使用智能指针的地方使用它们

与遗留代码交互 假设您有一个遗留的代码库,该代码库带有一个函数,该函数创建了一个数组,您必须在以后
delete[]
。如何使此代码异常安全?简单,将其存储在智能指针中

stuff* legacy_function();
// ...
std::unique_ptr<stuff[]> arr(legacy_function());
stuff*legacy_函数();
// ...
std::unique_ptr arr(遗留_函数());
类似场景:遗留功能希望拥有阵列的所有权:

std::unique_ptr<stuff[]> arr(new stuff[20]);
// do operations, possibly exception-throwing
other_legacy_function(arr.release());
std::unique_ptr arr(新材料[20]);
//执行操作,可能是异常抛出
其他旧功能(arr.release());
试着用
std::vector
这样做

虽然正确的解决方案是更改您的设计,但您不这么做可能有社会和实际原因(第三方代码?)。或者,也许你正在一步一步地重构代码

实现容器 没有理由不能在
std::unique\u ptr
之上实现容器。我看不出为什么编写手工容器的人不能从现有的“策略处理程序”中获益,而不是手动编写代码来满足三/五规则

总结
是的,你应该更喜欢集装箱。是的,
std::unique_ptr
没有那么有用

不是
unique_ptr
,而是
shared_ptr
对于实现引用计数数组可能很有用。不要将智能指针视为自删除指针,而是从所有权的角度来看待它们。这一点很好,但这与在智能指针中保留
std::array
有什么区别(除一个较低的间接层次外)?另一个问题是为什么他们使用
unique\u ptr
而不是
unique\u ptr
后者是有用的,与
std::array
不同,它可以容纳编译时大小未知的数组,并且不会邀请人们尝试像
std::vector
这样昂贵的大小更改操作。
std::unique\u ptr p(new int[5])
甚至不应该编译,您正在传递一个
int*
,其中构造函数需要一个指向大小为5的数组的指针。“它是实现定义的,但为了有良好的插入摊销时间,它通常会在每次增加向量时分配至少两倍的所需内容”不,不完全是