0

0

c++中如何禁用拷贝构造函数_c++ delete关键字【避坑】

尼克

尼克

发布时间:2026-02-10 12:27:11

|

757人浏览过

|

来源于php中文网

原创

delete拷贝构造函数后仍能编译通过,是因为编译器在拷贝被禁用时可能转而尝试移动;若移动也未定义,则报错——并非拷贝未禁用,而是退路缺失。

c++中如何禁用拷贝构造函数_c++ delete关键字【避坑】

为什么 delete 拷贝构造函数后仍能编译通过?

常见错觉是:只要写了 MyClass(const MyClass&) = delete;,就彻底禁用了拷贝。但实际中,如果类里没显式定义移动构造函数,而你又试图用右值初始化(比如返回临时对象),编译器可能因“删除了拷贝但没提供移动”而报错——不是因为拷贝没禁掉,而是它想退而求其次用移动,结果发现连移动也没有。

实操建议:

  • 禁用拷贝时,务必同步考虑移动语义:要么也 = delete 移动构造/赋值,要么显式定义它们
  • 若类本就不该被拷贝或移动(如封装了唯一资源句柄),两个都删更安全
  • 注意基类影响:若基类的拷贝构造函数是 protectedprivate,派生类即使没声明拷贝函数,也会隐式删除(编译失败)

= delete 放在 public 还是 private 区域?

必须放在 public 区域。很多人误以为“删掉就该藏起来”,于是写成 private: MyClass(const MyClass&) = delete; ——这反而会让错误信息变模糊:编译器先报“访问私有成员”,而不是“已删除”。用户无法第一时间意识到是设计上禁止拷贝,容易绕弯排查。

正确写法:

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

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;        // ← 必须 public
    NonCopyable& operator=(const NonCopyable&) = delete;
};

补充说明:

  • = delete 的函数即便在 public 区,也无法被调用;它的可见性只影响错误提示的清晰度
  • 不要用 private + 空实现替代 = delete:后者能在编译期拦截,前者拖到链接期甚至运行期才暴露问题

哪些场景下 = delete 比传统 private 声明更关键?

模板类或泛型代码中,= delete 是唯一可靠手段。例如你写了一个容器模板,想禁止对某些类型(如 std::unique_ptr)做拷贝构造:

Product Hunt
Product Hunt

Product Hunt每天都在寻找最好的新产品。

下载
template
class Box {
    Box(const Box&) = delete; // 错!太粗暴,所有 T 都禁了
    template
    Box(const Box&) = delete; // 也不行:SFINAE 不适用 delete 声明
};

更合理的做法是结合 std::is_copy_constructible_vstatic_assert,或对特化类型单独 = delete。但重点在于:= delete 是编译期强制策略,而传统 private 在模板实例化时可能根本不会触发(取决于是否被调用)。

其他典型场景:

  • 禁用特定参数类型的重载(如禁止从 int 构造):MyClass(int) = delete;
  • 禁用隐式转换构造函数,避免意外类型提升
  • 防止 std::vector 因内部拷贝操作失败而编译不过

继承 NonCopyable 基类时的坑

很多项目沿用旧式 boost::noncopyable 风格:基类把拷贝相关函数设为 private。但 C++11 后这已过时。问题在于:派生类若未显式声明拷贝构造函数,编译器会尝试合成——而合成规则要求基类的对应函数可访问。基类是 private,合成失败,报错信息却是 “use of deleted function”,非常误导。

现代写法应直接在派生类中 = delete

class Widget : private NonCopyable {  // ❌ 旧习惯,隐患多
    // ...
};

换成:

class Widget {
public:
    Widget(const Widget&) = delete;
    Widget& operator=(const Widget&) = delete;
    // 其他成员...
};

真正容易被忽略的是:如果派生类有成员变量是不可拷贝类型(如 std::unique_ptr),即使你不写任何 = delete,编译器也会自动删除拷贝构造函数——但这个隐式删除不等于“你控制了行为”,一旦后续加了可拷贝成员,它又悄悄复活,导致行为不一致。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
c语言const用法
c语言const用法

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

541

2023.09.20

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

668

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

555

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

205

2025.08.29

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

284

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

218

2023.12.29

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

490

2023.08.04

包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法

本专题汇总了包子漫画官网和网页版入口,提供最新章节抢先看方法、正版免费阅读指南,以及稳定访问方式,帮助用户快速直达包子漫画页面,无广告畅享全集漫画内容。

47

2026.02.10

热门下载

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

精品课程

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

共94课时 | 9.1万人学习

C 教程
C 教程

共75课时 | 4.6万人学习

C++教程
C++教程

共115课时 | 17万人学习

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

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