为什么我们需要delete运算符?(难道我们不能只使用delete[]吗?)

5
我今天读到有关deletedelete[]运算符的文章,我可以看到为了释放分配给myChar的内存,我应该调用delete,而为了释放myCharArray的内存,我应该使用delete[]
然而,我一直认为myChar是指向大小为1的数组的指针。那么为什么我们在这种情况下使用delete?为什么我们需要delete呢?如果myChar实际上是大小为1的数组,我们不能只使用delete[]吗?
char* myChar = new char;
char* myCharArray = new char[5];

delete myChar;
delete[] myCharArray;

2
因为每个 new 应该伴随着 delete,每个 new[] 应该伴随着 delete[]。实际上,你应该使用智能指针来代替。 - Ron
4
因为对象不是大小为1的数组。如果定义一个数组,那么该数组的大小会存储在内存的某个位置(这是由实现定义的)。如果使用delete[],它必须知道这个大小...但对于纯对象指针,没有这样的信息... - Jaa-c
2
仅仅因为在这个例子里它起作用,并不意味着它总是可靠的,存在未定义行为。想象一下你有一个带有虚拟析构函数的基类和派生类,如果你使用 Base *ptr = new Derived,那么如果你使用 delete[] ptr,编译器应该如何知道调用哪个析构函数? - Kaldrr
2
这里不会抛出异常,它是未定义的行为,而不是可能引发异常的操作。 - Kaldrr
3
重新开放:这个问题不是关于 deletedelete[]区别,而是关于它们为什么不同的原因。请翻译此内容。 - Pete Becker
显示剩余9条评论
2个回答

7
一个单独的对象并不是大小为1的数组。创建一个大小为1的数组(使用new char[1]),需要记录被分配的对象的数量,以便delete[]知道要销毁多少个对象。
可以说,new内部可以作为new[1]实现(并将delete实现为delete[])-这将是一种正确的实现。但是,有单独的newnew[1]允许优化不存储单个对象计数的情况(这是非常常见的情况)。
这里运用了C++的原则:不为你不使用的东西付费。如果我们创建对象数组,则会支付存储计数的内存和处理价格,但是如果我们创建单个对象,则不会产生额外的开销。

一个单一的对象,在许多情况下,是一个大小为1的数组。int i = 3; int* begin = &i; int* end = &(i + 1); while (begin != end) std::cout << *begin++; - Pete Becker
@PeteBecker 我认为这更多是数组衰减为指针的影响,而不是对象作为大小为1的数组。 - el.pescado - нет войне
@TobySpeight -- “在delete[]的上下文中,它们是不同的”只是在重述问题。 - Pete Becker
@Pete,我进行了编辑以更清晰地表明具有不同的newnew[](以及它们对应的deletedelete[])是一种优化。现在我是否更好地捕捉了本质? - Toby Speight

6

你说得对,new/deletenew[]/delete[]之间没有天然的区别;语言可以简单地省略非数组版本,或者省略delete并要求delete[]正确处理由new分配的单个对象。但这样做会增加实现单个对象情况下的复杂性和相应的开销,因为它随后必须在某处存储大小为1,以便delete[]能够执行正确的操作。C ++的主要设计原则之一是(并且仍然是)不支付您不使用的内容。 new/delete正是这种节俭的结果。它将成本从实现移动到程序员。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接