为何按C++核心准则,构造/析构函数成对用new/delete是错误?
关于C++核心准则中构造/析构函数成对使用new/delete的解释
首先纠正你的理解:这种写法并非语法上的绝对错误,但属于C核心准则明确指出的**高风险、不符合现代C最佳实践**的操作,强烈建议避免。
核心问题出在以下几点:
异常安全漏洞
如果构造函数中执行new后,后续代码抛出异常(比如另一个对象构造失败、调用的函数抛出异常),此时对象的构造并未完成,析构函数不会被调用,之前new分配的内存会直接泄漏。举个典型反例:class RiskyClass { private: int* num_ptr; ComplexObj* obj_ptr; public: RiskyClass() { num_ptr = new int(42); // 内存分配成功 obj_ptr = new ComplexObj(); // 假设这里抛出异常(比如ComplexObj构造失败) // 到这一步,构造中断,析构函数不会执行,num_ptr的内存永久泄漏 } ~RiskyClass() { delete num_ptr; delete obj_ptr; } };违反RAII核心原则
C++核心准则的核心思想之一是RAII(资源获取即初始化)——让资源的生命周期与对象绑定,由对象的构造/析构自动管理资源。手动在构造里new、析构里delete,本质是放弃了RAII的安全保障,把资源管理的责任丢给了开发者,极易出错。拷贝/移动操作的隐形风险
如果你的类没有手动实现拷贝构造、拷贝赋值、移动构造、移动赋值函数,编译器会生成默认版本,这些默认版本会做浅拷贝。如果多个对象持有同一个裸指针,当其中一个对象析构时释放了内存,其他对象的指针就会变成悬空指针,后续访问或析构都会触发未定义行为。
符合准则的正确写法
用智能指针(std::unique_ptr/std::shared_ptr)或标准容器来替代裸指针和手动内存管理:
class SafeClass { private: std::unique_ptr<int> num_ptr; std::unique_ptr<ComplexObj> obj_ptr; public: SafeClass() : num_ptr(std::make_unique<int>(42)), obj_ptr(std::make_unique<ComplexObj>()) {} // 不需要手动写析构函数!智能指针会在对象生命周期结束时自动释放资源 // 默认的拷贝/移动操作被禁用,避免浅拷贝风险;如需支持可手动实现 };
如果需要管理动态数组,直接用std::vector代替new[]和delete[],同样能自动处理内存分配与释放。
内容的提问来源于stack exchange,提问作者Mangy
相关产品推荐
相关产品推荐

