0

0

C++如何实现不可拷贝类?(delete拷贝构造函数)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-03-01 15:03:09

|

510人浏览过

|

来源于php中文网

原创

必须同时删除拷贝构造函数和拷贝赋值运算符,否则编译器会自动生成默认的拷贝赋值函数,导致类看似不可拷贝实则可赋值;c++11起应使用=delete显式禁用,且需注意继承、模板、资源语义等细节。

c++如何实现不可拷贝类?(delete拷贝构造函数)

为什么 delete 拷贝构造函数后类还是能被拷贝?

常见错误是只删了拷贝构造函数,却忘了拷贝赋值运算符。C++11 起,delete 一个不等于自动禁用另一个——两者必须都显式删除,否则编译器会生成默认的拷贝赋值函数,导致“看似不可拷贝实则可赋值”。

典型现象:MyClass a; MyClass b = a; 编译失败(正确),但 b = a; 却能通过(踩坑)。

  • 必须同时声明并 delete MyClass(const MyClass&)operator=(const MyClass&)
  • 若类有基类或成员含拷贝构造/赋值,它们也需满足不可拷贝约束,否则派生/组合时可能隐式调用成功
  • 移动操作不受影响——delete 拷贝不会自动禁用移动;如需禁用移动,也要单独 delete 移动构造和移动赋值

C++11 以后最简写法:用 = delete 显式禁止

别手写空实现或私有化加友元,那是 C++98 的过时方案。现代 C++ 直接在类内用 = delete 就行,语义清晰、编译期报错明确。

示例:

Subtxt
Subtxt

生成有意义的文本并编写完整的故事。

下载

立即学习C++免费学习笔记(深入)”;

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;
};
  • = delete 必须写在类定义内部(头文件中),不能只在 .cpp 里声明
  • 如果类有继承关系,基类已 = delete 拷贝操作,派生类仍需显式声明(否则编译器可能生成默认版本)
  • 注意:= default= delete 不能同时存在同一函数

哪些场景下必须手动禁用拷贝?

不是所有类都需要不可拷贝;滥用 = delete 反而限制接口灵活性。真正需要时,通常对应资源独占语义:

  • 封装了裸指针、文件句柄、socket、mutex 等非共享资源的对象
  • 设计为单例或全局唯一实例(如日志器、配置管理器)
  • 作为 RAII 容器持有唯一所有权(如 std::unique_ptr 的语义延伸)
  • 某些 STL 容器适配器(如 std::stack 默认底层容器是 std::deque,本身可拷贝;但若你用 std::unique_ptr 做成员,就得同步禁用拷贝)

容易忽略的兼容性细节

旧代码迁移到 C++11+ 时,常因宏或条件编译漏删拷贝函数。更隐蔽的问题是:模板推导或 SFINAE 场景下,= delete 函数仍参与重载决议,只是匹配后报错——这可能导致意外的编译失败而非静默跳过。

  • 若类被用于模板参数(如 std::vector<noncopyable></noncopyable>),需确保它支持移动(否则容器扩容失败)
  • 使用 auto 推导返回值时,若函数返回 NonCopyable 对象,且未启用返回值优化(RVO)或移动语义,编译会直接失败
  • 某些 IDE 或静态分析工具对 = delete 的诊断支持不全,建议用 -Wdeleted-function(GCC/Clang)确认是否真被触发
类不可拷贝这件事,关键不在“删掉两个函数”,而在理解对象生命周期与资源语义的绑定关系。删得不干净,或删得不合时宜,都会让问题延迟到运行时或集成阶段才暴露。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1560

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

240

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

128

2025.10.17

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

557

2023.09.20

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1708

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

549

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2332

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

42

2026.01.19

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

24

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.5万人学习

C 教程
C 教程

共75课时 | 5.1万人学习

C++教程
C++教程

共115课时 | 20万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号