为什么运行时环境不能决定应用 delete 或 delete[] 而不是程序员?

Why can't the runtime environment decide to apply delete or delete[] instead of the programmer?

本文关键字:delete 程序员 环境 运行时 不能 决定 应用 为什么      更新时间:2023-10-16

我读到delete[]操作符是需要的,因为运行时环境不保留有关分配的块是否是需要析构函数调用的对象数组的信息,但它实际上保留有关内存中存储分配块的位置的信息,当然还有块的大小。
只需要一个元数据来记住是否需要在删除时调用析构函数,所以为什么不这样做呢?

我相信一定有一个很好的解释,我不是在质疑它,我只是想知道它。

我认为原因是c++不会强迫你做任何你不想做的事情。它会增加额外的元数据,如果有人不使用它,额外的开销将强加给他们,这与c++语言的设计目标相反。

当你想要你所描述的功能时,c++ 确实提供了一种方法。它被称为std::vector,你应该几乎总是喜欢它,另一种容器,或者一个智能指针,而不是原始的newdelete

c++让你尽可能高效,所以如果他们必须跟踪块中的元素数量,那么每个块只会额外使用4个字节。

这对很多人来说可能很有用,但对于那些不介意把[]放在文件里的人来说,这也妨碍了整体效率。

这类似于c++和Java之间的区别。Java可以更快地编程,因为你永远不必担心垃圾收集,但c++,如果编程正确,可以更高效,使用更少的内存,因为它不需要存储任何这些变量,你可以决定何时删除内存块。

这基本上归结为语言设计不想对实现者施加太多限制。许多c++运行时对::operator new ()使用malloc(),对::operator delete ()使用free()(或多或少)。标准malloc/free不提供记录大量元素所需的簿记功能,也不提供在free时确定malloc 'd大小的方法。在new Foomalloc之间为每个对象添加另一个级别的内存操作,从C/c++的角度来看,在复杂性/抽象性方面是一个相当大的飞跃。除此之外,将这种开销添加到每个对象中会破坏一些内存管理方法,这些方法在设计时知道对象的大小。

这里有两件事需要澄清。

第一:假设malloc保持你要求的精确大小。

没有。malloc只关心提供一个足够大的块。尽管出于效率原因,它可能不会过度分配,但它仍然可能为您提供一个"标准"大小的块,例如2^n字节块。因此,实际大小(即实际分配的对象数量)实际上是未知的。

第二:所需的"额外位"

实际上,一个给定对象知道它是否是数组的一部分所需要的信息仅仅是一个额外的位。逻辑上。

就实现而言:您实际将该位放在哪里?

为对象本身分配的内存可能不应该被触及,毕竟对象正在使用它。

?
  • 在某些平台上,这可以保存在指针本身中(有些平台忽略部分位),但这是不可移植的
  • 所以它需要额外的存储空间,至少一个字节,除了对齐问题,它可能会达到8个字节。

示范:(不令人信服,如sth所述,见下文)

// A plain array of doubles:
+-------+-------+-------
|   0   |   1   |   2   
+-------+-------+-------
// A tentative to stash our extra bit
+-------++-------++-------++
|   0   ||   1   ||   2   ||
+-------++-------++-------++
// A correction since we introduced alignment issues
// Note: double's aligment is most probably its own size
+-------+-------+-------+-------+-------+-------
|   0   |  bit  |   1   |  bit  |   2   |  bit
+-------+-------+-------+-------+-------+-------

Humpf !

编辑

因此,在大多数平台上(地址很重要),你需要"扩展"每个指针,实际上是将它们的大小加倍(对齐问题)。

是否可以接受所有指针都是原来的两倍大,这样你就可以储存多余的位?我想对大多数人来说是这样的。但是c++不是为大多数人设计的,它主要是为那些关心性能的人设计的,无论是速度还是内存,因此这是不可接受的。

END OF EDIT

那么正确答案是什么呢?正确的答案是,恢复类型系统丢失的信息代价高昂。不幸的是。