The Rule of The Big Six指C++11起社区对六个关键特殊成员函数的统称:默认构造函数、析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符;手动定义其一通常需显式定义其余,以避免资源管理错误。
“The Rule of The Big Six”不是 C++ 标准里的正式术语,而是社区对 C++11 起(尤其 C++20 强化后)六个关键特殊成员函数的统称:它们共同决定一个类如何管理资源。如果你手动定义了其中任何一个,大概率需要显式定义其余几个,否则容易引发浅拷贝、重复释放、移动后访问野指针等问题。
它们是:
default constructor(默认构造函数)destructor(析构函数)copy constructor(拷贝构造函数)copy assignment operator(拷贝赋值运算符)move constructor(移动构造函数)move assignment operator(移动赋值运算符)注意:default constructor 有时被替换成 defaulted destructor 或省略——真正核心是后五个。C++20 中,= default 和 = delete 的语义更清晰,编译器对移动操作的隐式生成规则也更严格(比如:只要用户声明了任何拷贝/移动操作,编译器就不再自动生成移动构造/赋值)。
常见错误场景:你写了 ~MyClass() 来 delete 原生指针,但没写移动或拷贝函数:
class BadExample {
int* data;
public:
BadExample() : data(new int[100]) {}
~BadExample() { delete[] data; } // ✅ 析构写了
// ❌ 没写 copy/move —— 编译器会合成默认的(逐成员复制)
};后果:
data 被浅复制 → 两个对象指向
delete[]
~BadExample(),编译器就不再隐式声明移动构造/赋值(即它们变成 deleted),此时 std::vector 的 push_back 可能编译失败优先用 RAII 容器(如 std::vector、std::unique_ptr),避免裸指针。如果必须管理原生资源,按需显式定义:
BadExample(const BadExample&) = delete;、BadExample& operator=(const BadExample&) = delete;
std::string)→ 实现深拷贝 + 移动窃取(std::swap 或 nullptr 交换)= default(尤其移动函数在 C++20 中不会自动合成)示例(安全且符合 C++20):
class GoodExample {
std::unique_ptr data;
public:
GoodExample() : data(std::make_unique(100)) {}
~GoodExample() = default; // ✅ unique_ptr 自动清理
// ✅ 默认拷贝/移动都可用(unique_ptr 禁止拷贝、允许移动)
GoodExample(const GoodExample&) = delete;
GoodExample& operator=(const GoodExample&) = delete;
GoodExample(GoodExample&&) = default;
GoodExample& operator=(GoodExample&&) = default;
};
真正麻烦的永远不是“要不要写六个”,而是“你是否意识到某个函数正被隐式删除,而你的容器或算法正依赖它”。C++20 把这种隐式行为收得更紧,反而更容易暴露问题——这不是限制,是提示你该检查资源契约了。