智能指针如何在删除和删除[]之间进行选择?

spr*_*aff 33 c++ smart-pointers shared-ptr delete-operator c++11

考虑:

delete new std :: string [2];
delete [] new std :: string;
Run Code Online (Sandbox Code Playgroud)

每个人都知道第一个是错误.如果第二个不是错误,我们就不需要两个不同的运算符.

现在考虑:

std :: unique_ptr <int> x (new int [2]);
std :: unique_ptr <int> y (new int);
Run Code Online (Sandbox Code Playgroud)

是否x知道使用delete[]而不是 delete


背景:当我认为指针的数组类型限定将是一个方便的语言功能时,这个问题浮现在我脑海中.

int *[] foo = new int [2]; // OK
int *   bar = new int;     // OK
delete [] foo;             // OK
delete bar;                // OK
foo = new int;             // Compile error
bar = new int[2];          // Compile error
delete foo;                // Compile error
delete [] bar;             // Compile error
Run Code Online (Sandbox Code Playgroud)

Arm*_*yan 30

不幸的是,他们不知道他们使用什么删除使用delete.这就是为什么每个智能指针都有一个智能阵列对应的原因.

std::shared_ptr uses delete
std::shared_array uses delete[]
Run Code Online (Sandbox Code Playgroud)

那么,你的路线

std :: unique_ptr <int> x (new int [2]);
Run Code Online (Sandbox Code Playgroud)

实际上导致未定义的行为.

顺便说一句,如果你写

std :: unique_ptr<int[]> p(new int[2]);
                     ^^
Run Code Online (Sandbox Code Playgroud)

然后delete[]将使用,因为你明确要求.但是,以下行仍将是UB.

std :: unique_ptr<int[]> p(new int);
Run Code Online (Sandbox Code Playgroud)

他们无法选择的原因deletedelete[]new intnew int[2]是完全一样的类型- int*.

这里的中的情况下,使用正确的删除器的相关问题smart_ptr<void>,并smart_ptr<Base>Base没有虚析构函数.

  • @tenfour:因为类型完全一样! (6认同)
  • @tenfour:`(new int)`和`(new int [2])`都有类型`int*`,没有办法区分它们的模板特化. (6认同)
  • @spraff:不,`shared_ptr`对`T []`没有专门化. (3认同)
  • -1:谈论不存在的`std :: shared_array`. (3认同)
  • `typedef <typename T> using shared_array = shared_ptr <T []>;` (2认同)

Mat*_* M. 6

没有"神奇"的方法来检测a是否int*指的是:

  • 单个堆分配的整数
  • 堆分配的数组
  • 的整数堆分配的数组

类型系统丢失了信息,没有运行时方法(便携式)可以修复它.在C语言中,C语言继承了它的愤怒和严重的设计缺陷(*)(为了兼容性,有人说).

然而,处理与智能指针数组的一些方法.

首先,您的unique_ptr类型处理数组是不正确的,您应该使用:

std::unique_ptr<int[]> p(new int[10]);
Run Code Online (Sandbox Code Playgroud)

意味着调用delete[].我知道有人谈到在Clang中实现一个特定的警告来捕捉明显的不匹配unique_ptr:它是一个实施质量问题(标准只是说它是UB),并且并非所有情况都可以在没有WPA的情况下被覆盖.

其次,boost::shared_ptr可以有其中定制删除可能,如果你设计,它调用正确的delete[]操作.但是,有一个boost::shared_array特别为此设计的.再一次,检测到不匹配是一个实施质量问题.std::shared_ptr遭遇同样的问题(在ildjarn的评论之后编辑).

我同意这不漂亮.从C的起源到今天的设计缺陷(*)仍然如此令人讨厌.

(*)有些人会说C倾向于避免开销,这会增加开销.我部分不同意:malloc毕竟,总是知道块的大小.

  • C,没有函数重载和没有模板,并不像C++那样真正需要*严格的类型区别. (2认同)