@
hua123s 首先清楚大多数 C++ 用户不应该直接使用 new 和 delete 就够了。
具体原因么……替代的东西多了去了,没必要用;正常都是直接创建对象或者带所有权的智能指针( std::unique_ptr 和 std::shared_ptr )+不带所有权的引用 /视图( std::reference_wrapper/observer_ptr/string_view/span/...)。
两者的区别是,前者是非常底层的东西,必须自觉才能保证 no resource leak,并且还得小心才能保证 basic exception safety ;后者只要实现对(不滥用前者)默认就不会有这个问题。这种基本的 invariant guarantee 是在任何程序设计中都应当是普遍的重要的默认应该保持的东西,只不过不少语言根本不提供像 new 和 delete 这种依赖自觉不手贱才能维护 invariant 的危险操作,才让你看不出来这种保证的重要性。
要是几十年前古董代码用户水平又不够只会 new/delete 还能理解,现在正常情况一般代码根本不应该直接用这种底层而危险的东西。就算 new/delete 用对了不会导致功能问题,出现 new 而不能保证排除漏 delete 这种会导致最终用户直接受到影响(资源泄漏)的 invariant breakage,放任这种代码导致每个出现 new 的地方都要人肉找一遍 delete (因为这方面工具不保证完全靠谱)才能最终确保正确,这直接就是可维护性灾难。所以正常的 code review 就不应该放过这种低级问题,应用代码看到 new 和 delete 就直接回炉重造基本不会有错。
需要打死的还有一个理由是因为历史原因这方面实践普遍比较差,所以替代虽然理由应该明确,风格上也很混乱。很多大的项目可能自己有一套 API 做专门的封装。相比之下 Rust 就没 C++ 那么糟烂(但是也并不容易上手)。
另外不是给你看的,不过也算是基础内容(虽然大多数 C++ 用户这方面基础完全不合格,麻烦知耻):
1. new 不一定从 heap 上分配。new 底层实现的 operator new 作为 allocation function 且没被用户自定义时,分配的是 free store,而 heap 是 free store 在 hosted implementations 的一种普遍实现。这不是必要的。
2. 标准库提供默认的 placement new 就不分配。与此相对应该注意不遗漏是析构函数调用语法(……以及 std::launder 什么乱七八糟的),而不是 delete ; placement delete 仅在异常时被调用。