为什么我不能将new [ ]
与smart_poin一起使用?
实际上我无法理解这段文字。
警告您应该仅为auto_prt或shared_ptr对象使用 由new分配的内存,而不是new []分配的内存。您 不应该使用auto_ptr,shared_ptr或orunique_ptr作为内存 通过new分配,或者在unique_ptr的情况下,通过new或new []分配。
答案 0 :(得分:5)
为什么我不能将
new[]
与智能指针一起使用?
通常你可以,但智能指针必须知道它存储动态分配的数组而不是单个对象的事实。这是因为分配了运算符new[]
的对象应该使用运算符delete[]
,而不是 delete
取消分配。智能指针如何知道应该应用哪个运算符?
通过为数组类型提供智能指针类模板的特殊化来实现区别,就像目前在std::unique_ptr<T>
中完成的那样:
std::unique_ptr<int> ptr(new int); // will call delete
std::unique_ptr<int[]> arr(new int[5]); // will call delete[]
↑↑
但是,该语法(尚未)适用于标准库中可用的所有智能指针类型。
为了进行比较,Boost Smart Pointers库提供了单独的类模板,用于存储指向动态分配的数组的指针:
boost::shared_array<int> arr1(new int[5]); // will call delete[]
// ~~~~^
boost::scoped_array<int> arr2(new int[5]); // will call delete[]
// ~~~~^
您应该仅将
auto_ptr
或shared_ptr
对象用于由new
分配的内存,而不应用于由new []
分配的内存。
std::auto_ptr<T>
(†2017) 1 将普通delete
运算符应用于它存储的指针,并且无法更改该行为。因此,存储指向数组的指针不是一种选择。
就std::shared_ptr<T>
而言,默认情况下它会做同样的事情(调用operator delete
)。要更改该行为并正确释放存储阵列的内存区域,可以使用自定义删除器,如std::default_delete<T[]>
:
std::shared_ptr<int> arr(new int[5], std::default_delete<int[]>{});
↑↑
或您自己提供的其他一些内容:
std::shared_ptr<int> arr(new int[5], [](int* ptr) { delete[] ptr; } );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
但是,std::shared_ptr<T[]>
缺少专业化意味着没有operator[]
可以让您轻松访问存储数组的元素,从而导致语法不正确,如arr.get()[0]
。
引入了提案N4077,将数组类型指针的专门化:
std::shared_ptr<int[]> arr(new int[5]); // will call delete[]
↑↑
您不应将
auto_ptr
,shared_ptr
或unique_ptr
用于未通过new
分配的内存,或者在unique_ptr
的情况下,通过new
或new[]
。
此摘录简单地指出,不应该从指向未动态分配的对象的指针构造智能指针,因为(默认情况下)它会导致在未分配{的内容上调用delete
{1}}(同上new
/ new[]
)。
delete[]
,unique_ptr<double[]> p1(new double[2]);
,unique_ptr<double> p2(new double[2]);
之间的区别是什么?
unique_ptr<double[]> p3(new double(2));
确定:从两个std::unique_ptr<double[]> p1(new double[2]);
的数组的指针构造unique_ptr
(并获得所有权)。它将调用double
来释放指向的内存。
delete[]
错误:从两个std::unique_ptr<double> p2(new double[2]);
的数组的指针构造一个unique_ptr
(并获得所有权)。它将调用double
(!)来释放指向的内存。 (可能是未定义的行为 - delete
和new[]
之间的不匹配。)
delete
错误:从std::unique_ptr<double[]> p3(new double(2));
构建一个指向单 unique_ptr
的指针(并获得所有权),该指针已初始化为值{{1} }。它将调用double
(!)来释放指向的内存。 (可能是未定义的行为 - 2
和delete[]
之间的不匹配。)
1 new
被视为不赞成delete[]
,并且将根据{{从C ++ 1z中的标准库中删除3}}
答案 1 :(得分:1)
<强>示例:强>
#include <memory>
int
main()
{
auto p1 = std::unique_ptr<char[]>{new char[3]}; // C++11
auto p2 = std::shared_ptr<char>{new char[3], [](char* p) {delete [] p;}}; // C++11
auto p3 = std::make_unique<char[]>(3); // C++14
}
第一个和第二个适用于C ++ 11和转发。第3版是在C ++ 14中引入的。第一个和第三个代表新的唯一所有权,第二个拥有新的所有权。