C++ 我们为什么要删除由new分配的内存?
据说C++ 我们为什么要删除由new分配的内存?,c++,garbage-collection,C++,Garbage Collection,据说new分配的内存应该通过delete释放,但是现代桌面操作系统将回收内存,即使您不删除它。那么,我们为什么要删除由new分配的内存呢 另外,assert被称为不调用析构函数,它似乎在STL中被广泛使用(至少VS2015可以做到这一点)。如果建议删除由new分配的内存(像string、map和vector这样的类使用析构函数删除分配的内存),那么为什么开发人员仍然使用大量assert呢?如果不删除,就会导致内存泄漏。每次调用此运算符时,进程都会浪费部分地址空间,直到最终耗尽内存。如果不删除,则
new
分配的内存应该通过delete
释放,但是现代桌面操作系统将回收内存,即使您不删除它。那么,我们为什么要删除由new分配的内存呢
另外,assert
被称为不调用析构函数,它似乎在STL中被广泛使用(至少VS2015可以做到这一点)。如果建议删除由new
分配的内存(像string
、map
和vector
这样的类使用析构函数删除分配的内存),那么为什么开发人员仍然使用大量assert
呢?如果不删除,就会导致内存泄漏。每次调用此运算符时,进程都会浪费部分地址空间,直到最终耗尽内存。如果不删除,则会导致内存泄漏。每次调用此运算符时,进程都会浪费部分地址空间,直到最终耗尽内存
据说new
分配的内存应该由
删除
,但现代桌面操作系统将回收内存,即使
你不能删除它。那么,我们为什么要删除分配的内存呢
通过新建
小心!只有在程序完成后,操作系统才会回收内存。这与Java或C#中的垃圾收集不同,后者在程序运行时释放内存
如果您不delete
(或者更准确地说,如果您不确保delete
由std::unique_ptr
、std::string
或std::vector
等资源管理类调用,那么内存使用将继续增长,直到内存耗尽
更不用说析构函数不会运行,如果您有析构函数执行的不仅仅是释放内存的类型的对象,这一点很重要
另外,assert
被称为不调用析构函数
更准确地说,assert
会导致程序以不调用析构函数的方式终止,除非相应的翻译单元是使用定义的NDEBUG
预处理器宏编译的,在这种情况下,assert
不会执行任何操作
而且它似乎在STL中得到了广泛的应用(至少VS2015做到了这一点)
是的,Visual C++ 2015的标准库实现有很多。您还应该在自己的代码中自由地使用它来检测bug
C++标准本身没有指定如何以及如果代码> Asjt>/Cult>S应该出现在标准库函数的实现中。它确实规定了程序行为未定义的情况;这些通常对应于库实现中的
assert
(这是有意义的,因为如果行为没有定义,那么实现可以自由地做任何事情,那么为什么不以一种有用的方式使用这种自由来检测bug呢?)
如果建议删除由new
分配的内存(如
字符串
、映射
和向量
使用析构函数删除分配的
内存),那么为什么开发人员仍然使用大量的assert
因为如果断言失败,那么您希望程序立即终止,因为您检测到一个bug。如果您检测到一个bug,那么根据定义,您的程序处于未知状态。通过运行析构函数允许程序在未知状态下继续运行可能是危险的,并且可能会损害系统完整性和数据一致性
毕竟,正如我上面所说,析构函数可能不仅仅调用delete
几次。析构函数关闭文件、刷新缓冲区、写入日志、关闭网络连接、清除屏幕、加入线程或提交或回滚数据库事务。析构函数可以做很多事情,这些事情可能会修改并破坏系统资源
据说new
分配的内存应该由
删除
,但现代桌面操作系统将回收内存,即使
你不能删除它。那么,我们为什么要删除分配的内存呢
通过新建
小心!只有在程序完成后,操作系统才会回收内存。这与Java或C#中的垃圾收集不同,后者在程序运行时释放内存
如果您不delete
(或者更准确地说,如果您不确保delete
由std::unique_ptr
、std::string
或std::vector
等资源管理类调用,那么内存使用将继续增长,直到内存耗尽
更不用说析构函数不会运行,如果您有析构函数执行的不仅仅是释放内存的类型的对象,这一点很重要
另外,assert
被称为不调用析构函数
更准确地说,assert
会导致程序以不调用析构函数的方式终止,除非相应的翻译单元是使用定义的NDEBUG
预处理器宏编译的,在这种情况下,assert
不会执行任何操作
而且它似乎在STL中得到了广泛的应用(至少VS2015做到了这一点)
是的,Visual C++ 2015的标准库实现有很多。您还应该在自己的代码中自由地使用它来检测bug
C++标准本身没有指定如何以及如果代码> Asjt>/Cult>S应该出现在标准库函数的实现中。它确实规定了程序行为未定义的情况;这些通常对应于库实现中的
assert
(这是有意义的,因为如果行为仍然未定义)
int main(){
int* x = new int(1);
}
int main(){
while ( someCondition ) {
Foo* x = new Foo();
doSomething(*x);
} // <- already here we do not need x anymore
}
int main(){
while ( someCondition ) {
Foo x;
doSomething(x);
} // <- memory for x is freed automatically
}