为什么我不能在smart_pointers中使用`new []`?

Mik*_*ail 4 stl smart-pointers c++11

为什么我不能使用new [ ]smart_pointers?

其实我无法理解这段文字.

警告您应该将auto_prt或shared_ptr对象仅用于new分配的内存,而不是new []分配的内存.您不应该将auto_ptr,shared_ptr或orunique_ptr用于未通过new分配的内存,或者在unique_ptr的情况下,通过new或new []使用.

Pio*_*cki 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[]
                   ??
Run Code Online (Sandbox Code Playgroud)

DEMO

但是,该语法(尚未)适用于标准库中可用的所有智能指针类型.

为了进行比较,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[]
//            ~~~~^
Run Code Online (Sandbox Code Playgroud)

演示2


您应该仅为分配的内存使用auto_ptrshared_ptr对象new,而不是为分配的内存使用new [].

std::auto_ptr<T>(†2017)1将普通delete运算符应用于它存储的指针,并且无法改变该行为.因此,存储指向数组的指针不是一种选择.

就所std::shared_ptr<T>涉及的情况而言,默认情况下它是相同的(调用运算符delete).要更改该行为并正确释放存储阵列的内存区域,可以使用自定义删除器,如std::default_delete<T[]>:

std::shared_ptr<int> arr(new int[5], std::default_delete<int[]>{});
                                                            ??
Run Code Online (Sandbox Code Playgroud)

或者您自己提供的其他一些:

std::shared_ptr<int> arr(new int[5], [](int* ptr) { delete[] ptr; } );
//                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
Run Code Online (Sandbox Code Playgroud)

演示3

但是,缺少的特殊化std::shared_ptr<T[]>暗示没有operator[]可以让你轻松访问存储数组的元素,这导致不直观的语法,如arr.get()[0].

随着N4077的提议的引入,将有一个数组类型指针的专门化:

std::shared_ptr<int[]> arr(new int[5]); // will call delete[]
                   ??
Run Code Online (Sandbox Code Playgroud)

你不应该使用auto_ptr,shared_ptrunique_ptr用于存储通过不分配new,或在的情况下unique_ptr,通过newnew[].

这段摘录简单地指出,不应该从指向未动态分配的对象的指针构造智能指针,因为(默认情况下)它会导致调用delete未分配的东西new(ditto new[]/ delete[]).


是什么区别unique_ptr<double[]> p1(new double[2]);,unique_ptr<double> p2(new double[2]);, unique_ptr<double[]> p3(new double(2));

  1. std::unique_ptr<double[]> p1(new double[2]);

OK:构造一个unique_ptrfrom(并取得所有权)一个指向两个数组的指针double.它将调用delete[]释放指向的内存.

  1. std::unique_ptr<double> p2(new double[2]);

错误:构造一个unique_ptr指向两个数组的指针(并获得所有权)double.它会调用delete(!)来释放指向的内存.(可能是未定义的行为 - new[]和之间的不匹配delete).

  1. std::unique_ptr<double[]> p3(new double(2));

错误:构造一个unique_ptrfrom(并取得所有权)指向单个 double初始化为value 的指针2.它会调用delete[](!)来释放指向的内存.(可能是未定义的行为 - new和之间的不匹配delete[]).


从C++ 11开始,1std::auto_ptr<T>被认为是赞成使用std::unique_ptr<T>,并且根据N4168将从 C++ 1z中的标准库中删除.