当前位置: 首页 > news >正文

创建一个只能直接构造和销毁,但不能被复制和移动的基类

在这里有一段ROS的ControllerBase基类实现的代码,代码如下所示:

class ControllerBase
{
public:ControllerBase() = default;virtual ~ControllerBase() = default;ControllerBase(const ControllerBase&) = delete;ControllerBase& operator=(const ControllerBase&) = delete;ControllerBase(ControllerBase&&) = delete;ControllerBase& operator=(ControllerBase&&) = delete;

1. 这段代码的完整语义

代码意图很明显:
ControllerBase 是一个抽象基类(base class),默认构造和析构是允许的,但 禁止复制禁止移动
这样做可以让该类的对象不可被直接拷贝或移动,常用于:

  • 避免错误的拷贝(比如子类对象存在无法拷贝的资源)
  • 避免多个对象持有同一资源
  • 类似于单例模式资源管理类这种需要明确的对象生命周期控制的场景

2. delete 关键字在这里的作用

C++11 引入了 = delete 语法,表示显式禁用某个函数
当一个成员函数(包括构造函数、析构函数、赋值运算符等)被声明为 = delete 时:

  • 编译器不会为它生成定义
  • 如果代码里调用了这个函数,编译时会直接报错(而不是运行时报错)
  • 用于表达该操作在语义上是禁止的

在你的类中:

ControllerBase(const ControllerBase&) = delete;            // 删除拷贝构造函数
ControllerBase& operator=(const ControllerBase&) = delete; // 删除拷贝赋值运算符
ControllerBase(ControllerBase&&) = delete;                 // 删除移动构造函数
ControllerBase& operator=(ControllerBase&&) = delete;      // 删除移动赋值运算符

结果:

  1. ControllerBase 不能被用来拷贝构造

    ControllerBase a;
    ControllerBase b = a;  // ❌ 编译错误
    
  2. 不能被拷贝赋值

    ControllerBase a, b;
    a = b;  // ❌ 编译错误
    
  3. 不能被移动构造

    ControllerBase a;
    ControllerBase b = std::move(a);  // ❌ 编译错误
    
  4. 不能被移动赋值

    ControllerBase a, b;
    b = std::move(a);  // ❌ 编译错误
    

这样就保证了 ControllerBase 只能用唯一的对象实例,禁止复制或移动。


3. ControllerBase&& 的含义(右值引用)

ControllerBase&&右值引用(Right Value Reference)。
右值引用的主要用途是:

  1. 绑定到右值对象(临时对象、std::move 后的对象)
  2. 启用移动语义(避免不必要的深拷贝)
  3. 用于完美转发std::forward

例如:

ControllerBase&& r = ControllerBase(); // r 绑定到一个临时对象(右值)

在移动构造函数的上下文中:

ControllerBase(ControllerBase&& other);

表示接收一个来自右值的对象,这原本用于“偷取”它的资源(而不是拷贝),但你在这里加了 = delete
意味着即使传一个右值(例如 std::move(obj)),也不允许移动构造。


4. 为什么要同时删除左值引用版本和右值引用版本的构造/赋值?

原因是:

  • 如果你只删除了拷贝构造(const ControllerBase&),编译器会自动生成一个移动构造(ControllerBase&&
  • 如果你只删除了移动构造,编译器会用拷贝构造去替代
  • 为了彻底禁止复制和移动,必须两个都 delete

这样即保证了:

  • 不能 a = b;
  • 不能 a = std::move(b);
  • 不能 ControllerBase c = b;
  • 不能 ControllerBase c = std::move(b);

5. 总结表格

成员函数作用在代码中的状态
ControllerBase()默认构造函数默认允许
~ControllerBase()析构函数虚析构,允许
ControllerBase(const ControllerBase&)拷贝构造delete(禁止)
ControllerBase& operator=(const ControllerBase&)拷贝赋值delete(禁止)
ControllerBase(ControllerBase&&)移动构造delete(禁止)
ControllerBase& operator=(ControllerBase&&)移动赋值delete(禁止)

✅ 你这段代码的用途是:
创建一个只能直接构造和销毁,但不能被复制和移动的基类。

http://www.xdnf.cn/news/1434457.html

相关文章:

  • burpsuite使用之CaA神器使用
  • 2025年企业级数据服务API平台大全和接入指南
  • Text2SQL与DataAgent技术深度对比与实践指南
  • Java集合源码解析之LinkedList
  • 串口服务器技术详解:2025年行业标准与应用指南
  • 今天我们继续学习shell编程语言的内容
  • Vscode + docker + qt 网络监听小工具
  • 方差分析(通俗易理解)
  • Java代码耗时统计的5种方法
  • docker redis容器命令行操作
  • # pdf.js完全指南:构建现代Web PDF查看与解析解决方案
  • flume扩展实战:自定义拦截器、Source 与 Sink 全指南
  • 基于SQLite索引的智能图片压缩存储系统设计与实现
  • 【Vue】前端 vue2项目搭建入门级(二)
  • Arduino Uno与4×4矩阵键盘联动完全指南
  • Day11--HOT100--25. K 个一组翻转链表,138. 随机链表的复制,148. 排序链表
  • 模拟在线测试中相关语句的应用
  • Python如何处理非标准JSON
  • 百度网盘基于Flink的实时计算实践
  • Markdown格式.md文件的编辑预览使用
  • 【Java基础|第三十二篇】增强流、缓冲流、标准流、转换流
  • 【Qt】bug排查笔记——QMetaObject::invokeMethod: No such method
  • Telnet 原理与配置
  • Deepin25安装mysql8.4.5
  • 【鸿蒙面试题-6】LazyForEach 懒加载
  • MQTT报文的数据结构
  • LeeCode104. 二叉树的最大深度,LeeCode111. 二叉树的最小深度
  • 动手学深度学习
  • 2025年IT行业女性职业发展证书选择指南
  • 企业微信怎么用能高效获客?拆解体检品牌如何实现私域营收提升