news 2026/4/23 17:07:51

= delete和= default

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
= delete和= default

你想弄明白C++中= delete= default这两个语法的区别与用法,它们是C++11引入的核心特性,主要用于精准控制类的特殊成员函数(如构造函数、拷贝构造、赋值运算符等)。我会用通俗的语言+实战示例,讲清两者的核心用途、区别和使用场景,结合你之前接触的单例模式、类模板等场景加深理解。

一、核心定义(先立概念)

语法核心作用通俗理解
= default显式要求编译器生成默认版本的特殊成员函数(如默认构造、拷贝构造)“编译器,按你的默认规则帮我生成这个函数”
= delete显式禁用某个函数(让编译器拒绝生成/禁用调用)“编译器,这个函数我不用,禁止任何人调用”

二、= default:显式生成默认函数

1. 为什么需要= default

C++编译器会为类隐式生成默认构造、拷贝构造、赋值运算符、析构函数等特殊成员函数,但如果类中自定义了某些函数(如带参数的构造函数),编译器就会停止生成默认版本。= default可以强制编译器重新生成这些默认函数,既保留自定义逻辑,又不丢失默认行为。

2. 实战示例
#include<iostream>usingnamespacestd;classPerson{private:string name;intage;public:// 自定义带参数的构造函数(编译器不再生成默认构造)Person(string n,inta):name(n),age(a){}// 显式要求编译器生成默认构造函数(= default)Person()=default;// 显式要求编译器生成默认拷贝构造函数Person(constPerson&)=default;// 显式要求编译器生成默认赋值运算符Person&operator=(constPerson&)=default;// 显式要求编译器生成默认析构函数~Person()=default;voidshow(){cout<<"name: "<<name<<", age: "<<age<<endl;}};intmain(){// 调用默认构造函数(因= default生效)Person p1;p1.show();// 输出:name: , age: 0// 调用自定义构造函数Personp2("Tom",18);p2.show();// 输出:name: Tom, age: 18// 调用默认拷贝构造函数Person p3=p2;p3.show();// 输出:name: Tom, age: 18// 调用默认赋值运算符p1=p2;p1.show();// 输出:name: Tom, age: 18return0;}
3. 关键细节
  • = default只能用于编译器可自动生成的特殊成员函数(默认构造、拷贝构造、移动构造、赋值运算符、析构函数等),不能用于普通函数;
  • = default生成的函数比手动写的“空函数”更高效(编译器会优化为原生代码);
  • 示例中如果不加Person() = default;Person p1;会编译报错(编译器未生成默认构造)。

三、= delete:显式禁用函数

1. 为什么需要= delete

用于禁止某些函数的调用或生成,最常见场景是:

  • 禁用拷贝构造/赋值运算符(如单例模式,保证实例唯一);
  • 禁用特定类型的函数重载(如禁止int隐式转换为double);
  • 禁用编译器自动生成的特殊成员函数。
2. 实战场景1:单例模式(禁用拷贝/赋值)

这是你之前接触的场景,用= delete保证类实例唯一:

#include<iostream>usingnamespacestd;classSingleton{private:staticSingleton instance;// 私有构造函数(禁止外部创建)Singleton(){cout<<"Singleton创建"<<endl;}// 禁用拷贝构造(= delete)Singleton(constSingleton&)=delete;// 禁用赋值运算符(= delete)Singleton&operator=(constSingleton&)=delete;public:staticSingleton&getInstance(){returninstance;}};Singleton Singleton::instance;intmain(){Singleton&s1=Singleton::getInstance();// 以下代码编译报错(因拷贝/赋值被禁用)// Singleton s2 = s1;// Singleton s3;// s3 = s1;return0;}
3. 实战场景2:禁用特定函数重载
#include<iostream>usingnamespacestd;// 函数模板:计算两个数的和template<typenameT>Tadd(T a,T b){returna+b;}// 禁用int版本的add(= delete)template<>intadd<int>(inta,intb)=delete;intmain(){// 正常调用double版本cout<<add(3.14,5.67)<<endl;// 输出:8.81// 编译报错(int版本被delete)// cout << add(1, 2) << endl;return0;}
4. 关键细节
  • = delete可用于任意函数(特殊成员函数、普通函数、模板函数),比= default适用范围广;
  • = delete的函数即使声明了,也无法调用(编译期直接报错);
  • C++03中禁用拷贝构造的方式是“声明为private且不实现”,C++11后推荐用= delete(更清晰、编译期检测)。

四、= defaultvs= delete核心区别

维度= default= delete
核心目的让编译器生成默认版本的函数让编译器禁用某个函数(拒绝生成/调用)
适用范围仅特殊成员函数(编译器可自动生成的)任意函数(特殊成员、普通函数、模板函数)
编译行为生成函数代码,允许调用拒绝生成函数代码,调用时报错
典型场景自定义构造后恢复默认构造、优化默认函数单例禁用拷贝、禁止特定类型的函数调用

五、常见坑点与最佳实践

1. 坑点1:误用= default/= delete
// 错误:普通函数不能用= defaultvoidfunc()=default;// 错误:析构函数delete后,类无法实例化(对象销毁时需要析构)~Person()=delete;Person p;// 编译报错
2. 坑点2:默认函数的生成规则
  • 如果类中自定义了析构函数,编译器不再自动生成移动构造/移动赋值;
  • 如果用= delete禁用了拷贝构造,编译器也不会自动生成移动构造;
  • 建议:要么显式用= default指定,要么显式用= delete禁用,避免依赖编译器的隐式规则。
3. 最佳实践
  • 单例模式:必用= delete禁用拷贝构造和赋值运算符;
  • 需要默认构造但又自定义了带参构造:用= default恢复默认构造;
  • 禁止隐式类型转换:用= delete禁用特定重载(如add(int));
  • 优化性能:对编译器自动生成的函数用= default(比手动写空函数高效)。

总结

  1. = default:显式要求编译器生成默认版本的特殊成员函数,解决“自定义构造后丢失默认函数”的问题,且更高效;
  2. = delete:显式禁用函数,核心用于单例模式禁用拷贝、禁止特定函数调用,是C++11后替代“私有不实现”的最佳方式;
  3. 两者都是C++11的语法糖,核心价值是精准控制类的函数生成规则,让代码更清晰、更符合预期;
  4. 记忆口诀:default是“要默认”,delete是“要禁用”。

这两个语法在现代C++(尤其是嵌入式、高性能开发)中非常常用,掌握它们能让你写出更规范、更高效的类设计代码。

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

国标GB/T4857.5-1992跌落测试,GB/T4857.5跌落试验标准讲解

GB/T 4857.5-1992《包装 运输包装件 跌落试验方法》作为运输包装件基本试验体系的关键标准&#xff0c;等效采用ISO 2248:1985标准&#xff0c;为包装件抗垂直冲击性能检测提供了统一、规范的技术依据&#xff0c;是保障产品流通安全的重要技术支撑。 该试验的核心目的的是模拟…

作者头像 李华
网站建设 2026/4/23 15:51:14

Python自动化测试:线上流量回放

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快在自动化测试中&#xff0c;线上流量回放是一项关键技术&#xff0c;可以模拟真实用户的请求并重现线上场景&#xff0c;验证系统的性能和稳定性。本文将介绍Python…

作者头像 李华
网站建设 2026/4/23 14:32:31

一个注解搞定接口返回数据脱敏...

01 背景 下午惬意时光&#xff0c;突然产品小姐姐走到我面前&#xff0c;打断我短暂的摸鱼 time&#xff0c;企图与我进行深入交流&#xff0c;还好我早有防备没有闪&#xff0c;打开瑞 star 的点单页面&#xff0c;暗示没有一杯 coffee 解决不了的需求。 需求是某些接口返回…

作者头像 李华
网站建设 2026/4/23 11:25:56

如何设计接口测试用例?

接口测试用例设计其实跟功能测试用例设计是类似的&#xff0c;从根本上来说都是验证产品功能的实现情况。但是功能测试偏向于测试前端数据的展示、业务逻辑&#xff0c;但是有些情况是前端无法模拟的&#xff08;如前端的支付金额无法为负值&#xff09;&#xff0c;此时就需要…

作者头像 李华
网站建设 2026/4/23 12:57:58

日化产品想贴牌?源头厂家直供,成本降一半

想要打造属于自己的洗发水、洗衣液、面膜或者洗手液品牌吗?贴牌生产&#xff08;OEM&#xff09;确实是一条最为快捷的路径。但许多刚开始涉足这个领域的新手&#xff0c;在第一步就遇到了麻烦&#xff1a;他们找不到真正的源头厂家&#xff0c;反而被贸易商一层又一层地加价&…

作者头像 李华
网站建设 2026/3/29 11:25:55

JAVA理发预约系统:同城服务秒速响应

JAVA理发预约系统&#xff1a;同城服务秒速响应&#xff0c;打造高效、智能、个性化的美发体验 在快节奏的都市生活中&#xff0c;理发作为高频刚需服务&#xff0c;用户对“快速预约、精准匹配、透明服务”的需求日益迫切。JAVA凭借其跨平台、高并发、安全稳定等特性&#xff…

作者头像 李华