为什么C++仍然有delete[]和delete操作符?

5

使用单个关键字实现数组删除难吗?它的效率是否降低?


3
我犹豫是否将其标记为“不是一个真正的问题”,尽管表述不是太好,但它确实询问了统一背后的技术挑战;我相信这些挑战可以得到解决。 - Matthieu M.
相关问题:https://dev59.com/lHRB5IYBdhLWcg3wJkhC - Fred Larson
4个回答

15

首先,让我总结一下它们的作用: delete 调用一个对象的析构函数并释放内存;delete[] 调用一些对象的析构函数并释放内存。

可以将它们合并为同一个操作:“调用一些对象的析构函数并释放内存”。毕竟,one 也是 some 中的一种。

无论是 delete 还是 delete[] 都在指针上进行操作,就像这个:

foo* ptr;

仔细看看它,告诉我当我们delete它时应该调用多少析构函数。你无法知道,编译器也一样。这只能在运行时确定。关于对象数量的信息必须被存储在某个地方。这意味着,对于每个new[]的使用,都会分配一些额外的内存来跟踪该数量。

C++建立在“不付费用”的原则之上,这就是为什么非数组形式存在的原因:由于delete始终仅删除一个对象,new不需要分配任何额外空间。


更准确地说,这是一个遗留问题。执行 delete(1, ptr)delete(expression, ptr); 是微不足道的。每个人都知道他们有多少元素。 - Puppy
2
Malloc 知道为分配请求分配了多少内存。 delete 可以查询相同的信息。 - jxh
3
如果扩展C库以报告为指针分配了多少内存,那么C++可以轻松地允许delete的行为像delete[],问候。 - jxh
4
@user315052 不行。就算是这种情况,由 malloc 存储的信息也是错误的。它所存储的是在某个块中分配的存储量,通常按某些特殊边界对齐,因此可能大于在那里构造的对象的实际大小。但是,delete[] 需要的是对象数量,而不是为它们分配的存储空间的大小。在 C 语言中这并不相关,因为没有析构函数。 - R. Martinho Fernandes
1
@DeadMG 真的吗?你应该看看 C 语言中人们为字符串所做的事情。通常,你不需要(甚至不想要)分配的元素数量,你需要的是有效元素的数量。如果你不知道要读取多少个 chardouble,你可以分配一百万个,然后返回指针,带有计数器为 10,因为那是你实际读取的数量。 - James Kanze
显示剩余6条评论

6
问题不在于复杂性,而在于delete的参数是单个指针,而且无论您分配单个元素还是数组,该类型都完全相同。在底层实现方面存在很大的差异,因为销毁的元素数量不同。
实际上,这是与C的向后兼容性有关的问题......如果从一开始就没有这个要求,我们可能不会有C++(它不会追赶那么多),但new T[N]的类型可能与new T的类型不同,并且可以使用类型系统来检测需要调用哪个delete

1
我猜OP真正想知道为什么 new Tnew T[1]有什么不同。 - Oliver Charlesworth
这可能会引起一个问题:“如果我正在新建一个Gizmos数组,我是否真的想要仅调用第一个元素的构造函数?” - John Dibling
2
正如我在答案中所说的:new T[1]有额外的开销,你不应该为你不使用的东西付费。 - James Kanze

5

这是因为C++设计的一个重要原则是,不使用的部分不需要支付额外的代价。new[]/delete[]有额外的成本,并且人们认为它们的实用性(我在25年的C++编程中从未使用过它们)非常有限,不足以证明将此成本添加到非数组new/delete中。


-3

即使实现起来很容易,也不能从语言中轻易删除此类功能。在进行这样的更改后,你们愿意自愿前来修复我的代码吗?


1
如果delete[]语法已经过时但仍然可以使用,他们本来可以将其废弃而不必删除它,并使符合规范的实现将一个委托给另一个。 - Mark Ransom
他们废弃auto_ptr没有遇到任何问题。 - John Dibling
auto_ptr是一个库类,而不是语言结构,因此它并不相同。如果你问我,强制实施这种复杂的有用特性是完全愚蠢的。 - Nikolai Fetissov

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