Rule of Zero 是现代 C++ 资源管理原则,主张不手动定义任何特殊成员函数,而将资源交由 RAII 类型(如智能指针、标准容器)自动管理,从而获得正确且安全的拷贝、移动和析构行为。

Rule of Zero 是现代 C++ 中提倡的一种资源管理原则:如果类不需要显式定义析构函数、拷贝/移动构造函数或拷贝/移动赋值运算符(即“特殊成员函数”),就**一个都不要写**——让编译器自动生成,同时把资源交给 RAII 类型(如智能指针、标准容器)来管理。
Rule of Zero 的核心思想
它不是说“零资源管理”,而是“零手动管理”。重点在于:把资源封装进已正确实现 RAII 的类型里,从而让外层类自动获得正确的拷贝、移动和析构行为。
- 类中只包含能自动管理资源的成员(std::unique_ptr、std::shared_ptr、std::vector、std::string 等)
- 不写析构函数 → 编译器生成的析构函数会自动调用各成员的析构函数,释放资源
- 不写拷贝/移动函数 → 编译器生成的版本会按成员逐个拷贝或移动,智能指针会正确处理所有权转移
- 一旦需要手写任意一个特殊成员函数,就要重新审视是否违反了 Rule of Zero —— 很可能该资源该交给更底层的 RAII 类型去管
用智能指针替代裸指针,轻松满足 Rule of Zero
传统裸指针容易导致内存泄漏、重复释放或浅拷贝问题。换成 std::unique_ptr 或 std::shared_ptr 后,资源生命周期由对象自身控制,无需干预。
- std::unique_ptr:独占所有权,不可拷贝,可移动 → 适合“我创建,我销毁”的场景
- std::shared_ptr:共享所有权,带引用计数 → 适合多处需要访问同一资源的场景
- 示例:原来要手写析构释放
int*,现在直接用std::unique_ptr,类里连~MyClass()都不用写
一个对比示例:从 Rule of Three 到 Rule of Zero
假设有类管理动态数组:
立即学习“C++免费学习笔记(深入)”;
❌ 手动管理(Rule of Three):class BadArray {
int* data_;
size_t size_;
public:
BadArray(size_t n) : data_(new int[n]), size_(n) {}
~BadArray() { delete[] data_; } // 必须写
BadArray(const BadArray& other) : data_(new int[other.size_]), size_(other.size_) {
std::copy(other.data_, other.data_ + size_, data_);
}
BadArray& operator=(const BadArray& other) { /* 深拷贝实现 */ }
};✅ 改用 Rule of Zero:
class GoodArray {
std::vector data_; // 或 std::unique_ptr data_;
public:
explicit GoodArray(size_t n) : data_(n) {} // 不再需要析构/拷贝/移动函数
}; 编译器自动生成的特殊成员函数完全正确:拷贝时 std::vector 自动深拷贝,移动时高效转移内部缓冲区,析构时自动释放内存。
什么时候不能用 Rule of Zero?
并非所有情况都适用,但关键在于:**问题不在 Rule of Zero,而在资源封装层级是否合理**。
- 需要定制释放逻辑(如关闭文件描述符、卸载 OpenGL 资源)→ 封装成独立 RAII 类型(如
FileHandle),再在主类中组合它 - 需要禁用拷贝(仅支持移动)→ 仍可遵守 Rule of Zero,只需将拷贝函数 = delete,移动函数让编译器生成(C++11 起默认生成移动操作)
- 性能敏感且需避免任何开销 → 极少数场景下需手工优化,但应先测量,而非预设
Rule of Zero 让代码更安全、更简洁、更易维护。智能指针不是“替代方案”,而是实现它的自然工具。把资源托付给标准库的 RAII 类型,你就已经走在现代 C++ 的正路上了。










