零规则优先,用RAII封装资源使类无需自定义特殊成员函数;若需手动管理,则应遵循三规则(析构、拷贝构造、拷贝赋值)或五规则(增加移动构造、移动赋值),确保资源安全与异常安全。
这是C++中关于资源管理的一组指导原则,核心是:当你需要显式定义某个特殊成员函数时,往往意味着你需要同时考虑其他几个——否则容易引发资源泄漏、重复释放或对象状态不一致等问题。
优先通过封装来避免手动管理资源。如果类的所有成员都支持自动资源管理(比如用std::vector代替int*,用std::string代替char*),那么你就不需要自己写析构函数、拷贝/移动构造函数或赋值运算符。编译器生成的默认版本就完全安全可靠。
例如:
如果你不得不定义了析构函数、拷贝构造函数、拷贝赋值运算符中的任意一个,通常三个都需要显式定义。因为这说明类在管理某种非自动资源(比如动态分配的内存),而默认的拷贝行为是浅拷贝,会导致两个对象指向同一块内存,析构时重复释放。
典型场景:
C++11引入移动语义后,三规则扩展为五规则:若需自定义析构、拷贝构造、拷贝赋值,通常也需定义移动构造和移动赋值。否则,移动操作会退回到调用拷贝版本(如果没禁用),失去性能优势;更糟的是,若你只写了析构和拷贝,但没禁用移动,编译器可能自动生成移动函数,而它们默认执行位移(bitwise move)——对含裸指针的类来说,这会让原对象残留悬空指针。
稳妥做法:
Rule of Zero 是首选目标;实在绕不开资源管理时,优先用
std::unique_ptr、std::shared_ptr等智能指针替代裸指针;只有在性能敏感且无法使用标准工具时,才手写符合 Rule of Five 的完整集合,并确保五个函数逻辑自洽、异常安全。