三法则与五法则
正确管理复制和移动
三法则与五法则 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
三法则
如果一个类需要自定义析构函数,那么它几乎总是也需要自定义拷贝构造函数和拷贝赋值运算符。这三者总是成套出现。
为什么是三个
管理裸资源的类必须定义资源如何被销毁、复制和赋值——否则编译器生成的浅拷贝会导致重复释放。
#include <iostream>
class Bad {
int* p;
public:
Bad(int v) : p(new int(v)) {}
~Bad() { delete p; }
// default copy => two objects delete the same p!
};自定义拷贝构造函数
正确的拷贝构造函数会执行深拷贝,分配属于自身的资源,而不是与其他对象共享资源。
#include <iostream>
class Box {
int* p;
public:
Box(int v) : p(new int(v)) {}
Box(const Box& o) : p(new int(*o.p)) {} // deep copy
~Box() { delete p; }
int get() const { return *p; }
};
int main() {
Box a(5);
Box b = a; // independent copy
std::cout << b.get() << "\n";
}自定义拷贝赋值
拷贝赋值必须释放旧资源,防止自赋值,并对新值执行深拷贝。
Box& operator=(const Box& o) {
if (this != &o) { // self-assignment guard
delete p;
p = new int(*o.p);
}
return *this;
}五法则
C++11 增加了移动操作。如果您定义了五个特殊成员函数中的任意一个(析构函数、拷贝构造、拷贝赋值、移动构造、移动赋值),就应考虑将五个全部定义出来。
移动构造函数
移动构造函数会从临时对象中接管资源,并使源对象变为空——这比拷贝的代价低得多。
Box(Box&& o) noexcept : p(o.p) {
o.p = nullptr; // source left empty
}移动赋值
移动赋值会释放当前资源,然后接管源对象的资源。
Box& operator=(Box&& o) noexcept {
if (this != &o) {
delete p;
p = o.p;
o.p = nullptr;
}
return *this;
}将移动操作标记为 noexcept
移动操作应标记为 noexcept,这样容器(例如 std::vector)在重新分配时就能安全地使用它们。
零法则
最理想的做法是:不要直接拥有任何原始资源。使用 std::unique_ptr、std::vector 或 std::string,这样您就可以不定义五个特殊成员函数中的任何一个——编译器生成的默认版本就是正确的。
#include <memory>
class Good {
std::unique_ptr<int> p; // owns the resource for you
public:
Good(int v) : p(std::make_unique<int>(v)) {}
// no destructor, no copy/move needed
};删除操作
如果拷贝没有意义,就将其删除:Box(const Box&) = delete;。这样可以有意地让类型只能移动或不可拷贝。
选择正确的法则
应以零法则为目标。只有在确实封装了标准库无法处理的原始资源时,才退而采用五法则。
快速检查
请测试您对三法则/五法则的理解。
回顾
您已经学习了三法则/五法则:管理原始资源意味着要一致地定义析构、拷贝和移动操作。请将移动操作标记为 noexcept。最理想的做法是使用标准 RAII 类型,遵循零法则,一个特殊成员函数都不定义。
常见问题解答
「三法则与五法则」课时是免费的吗?
是的 — 「三法则与五法则」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「三法则与五法则」这节课中我会学到什么?
正确管理复制和移动 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「三法则与五法则」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。