news 2026/4/16 2:23:59

= 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/4 16:14:56

JAVA旅游系统:畅享一站式智慧出行

JAVA旅游系统通过整合多端接入、智能推荐、实时数据处理与高并发架构&#xff0c;为用户提供了一站式智慧出行体验&#xff0c;显著提升了旅游服务的便捷性与个性化水平。以下是具体分析&#xff1a;一、技术架构&#xff1a;稳定高效&#xff0c;支撑高并发场景跨平台兼容性JA…

作者头像 李华
网站建设 2026/4/10 17:20:31

使用工具Postman快速导出python接口测试脚本

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快Postman的脚本可以导出多种语言的脚本&#xff0c;方便二次维护开发。Python的requests库&#xff0c;支持python2和python3&#xff0c;用于发送http/https请求使用…

作者头像 李华
网站建设 2026/4/7 9:15:53

Git 中的 Rebase 与 Merge:原理、区别与最佳实践

文章目录1. 引言&#xff1a;为什么 Git 会有 rebase 和 merge 两种方式&#xff1f;2. Git Merge&#xff1a;保留真实历史的合并2.1 Merge 的基本思想2.2 Merge 的使用方式2.3 Merge 的优点2.4 Merge 的缺点3. Git Rebase&#xff1a;重写历史的“整理术”3.1 Rebase 的基本思…

作者头像 李华