news 2026/6/9 21:26:00

C++ 中三法则五法则零法则

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 中三法则五法则零法则

三法则

C++98/03 年代:如果一个类需要显式定义以下三者之一,那么它很可能需要显式定义所有三个:

析构函数

拷贝构造函数

拷贝赋值运算符

原因:如果一个类需要自定义析构函数,通常是因为它管理着动态内存或其他资源(例如文件句柄、网络连接等)。那么,当进行拷贝时(通过拷贝构造函数或拷贝赋值运算符),如果使用编译器生成的默认拷贝操作,会导致浅拷贝(即只拷贝指针,而不拷贝指针指向的资源),从而可能造成双重释放、内存泄漏等问题。因此,需要自定义拷贝操作来实现深拷贝或适当的资源管理。

classRuleOfThree{char*data;// 动态分配的资源public:RuleOfThree(constchar*str){data=newchar[strlen(str)+1];strcpy(data,str);}// 1. 需要自定义析构函数来释放资源~RuleOfThree(){delete[]data;}// 2. 拷贝构造函数(深拷贝)RuleOfThree(constRuleOfThree&other){data=newchar[strlen(other.data)+1];strcpy(data,other.data);}// 3. 拷贝赋值运算符(深拷贝)RuleOfThree&operator=(constRuleOfThree&other){if(this!=&other){delete[]data;// 释放原有资源data=newchar[strlen(other.data)+1];strcpy(data,other.data);}return*this;}};

五法则

五法则指出:如果一个类需要显式定义拷贝操作、移动操作或析构函数中的任何一个,那么它很可能需要显式定义以下五个:

  1. 析构函数
  2. 拷贝构造函数
  3. 拷贝赋值运算符
  4. 移动构造函数
  5. 移动赋值运算符
    原因:当一个类管理资源时,除了三法则中的三个函数,我们还应该考虑移动操作。通过定义移动操作,我们可以避免不必要的拷贝,提高效率。移动操作将资源从源对象转移到目标对象,同时使源对象处于有效但不可用的状态(通常为空)。
classRuleOfFive{char*data;public:RuleOfFive(constchar*str=""){data=newchar[strlen(str)+1];strcpy(data,str);}// 1. 析构函数~RuleOfFive(){delete[]data;}// 2. 拷贝构造函数RuleOfFive(constRuleOfFive&other){data=newchar[strlen(other.data)+1];strcpy(data,other.data);}// 3. 拷贝赋值运算符RuleOfFive&operator=(constRuleOfFive&other){if(this!=&other){delete[]data;data=newchar[strlen(other.data)+1];strcpy(data,other.data);}return*this;}// 4. 移动构造函数(从临时对象“窃取”资源)RuleOfFive(RuleOfFive&&other)noexcept:data(other.data){other.data=nullptr;// 使源对象处于有效状态(可析构)}// 5. 移动赋值运算符RuleOfFive&operator=(RuleOfFive&&other)noexcept{if(this!=&other){delete[]data;data=other.data;other.data=nullptr;}return*this;}};

零法则

在现代C++中,还有一个重要的原则叫零法则。它建议:让类依赖自动生成的默认操作,而将资源管理委托给专门的资源管理类(如std::string, std::vector, std::unique_ptr等)。这样,我们就不需要自定义析构函数、拷贝/移动操作,编译器生成的默认行为就是正确的。

classRuleOfZero{std::string data;// 使用标准库字符串管理动态内存public:RuleOfZero(conststd::string&str):data(str){}// 不需要定义析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符// 编译器自动生成的版本会正确调用std::string的相应操作。};

总结

三法则:适用于C++98/03,涉及拷贝控制和析构。

五法则:适用于C++11及以后,增加了移动控制。

零法则:现代C++的最佳实践,通过使用RAII对象管理资源,避免手动管理。

在编写类时,应优先考虑零法则,如果必须手动管理资源(例如设计底层资源管理类),则遵循五法则。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 20:57:03

接口测试流程和步骤

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是接口测试我们要想知道接口测试怎么做,首先要明白接口测试是什么?一般像系统内的组件接口数据交互测试、不同系统与系统之间的接口数据交…

作者头像 李华
网站建设 2026/6/9 21:08:12

接口测试:使用Requests库发送POST请求

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快POST请求用于向服务器提交数据,比如提交一个表单新建一个用户、或修改一个用户信息等操作。对于POST请求,我们可以通过浏览器开发者工具或者…

作者头像 李华
网站建设 2026/6/9 19:49:17

基于RAG技术打造知识库问答系统:Python实现与工程化部署详解

大家好!今天我们来学习如何使用Python实现一个基于RAG(检索增强生成)的知识库问答系统。这个系统能够基于我们自己的文档资料来回答问题,让AI更懂"我们的业务"。 1. RAG技术简介 RAG技术就像是给AI装了一个"活字典"。不同于传统大…

作者头像 李华
网站建设 2026/6/9 19:51:19

Jmeter基础:Jmeter聚合报告详解

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 1、聚合报告介绍在使用JMeter进行性能测试时,聚合报告(Aggregate Report)可以说是必用的监听器。(1)聚合报告的生成方式聚合报…

作者头像 李华