C++中不能复制只能移动的类型

在 C++ 中,不能复制(Non-Copyable)但可以移动(Movable) 的类型通常是那些用于管理独占性资源的类。

这些类的设计目标是确保在任何给定时间,只有一个对象拥有该资源的所有权,从而防止资源被重复释放或发生混乱。

核心类型:独占性资源管理器

以下是 C++ 标准库中一些最重要、最常见的只能移动不能复制的类型:

1. 内存和资源所有权管理
类型 托管的资源 为什么不能复制?
std::unique_ptr 独占性地管理堆上的动态内存。 如果复制,两个指针将指向同一块内存。当其中一个析构时,内存会被释放,另一个指针将变成悬空指针(Dangling Pointer)。
std::fstream / std::ifstream / std::ofstream 文件句柄(File Handle)。 复制会导致两个对象试图管理同一个操作系统文件描述符,可能导致关闭两次或访问冲突。
std::thread 操作系统线程的执行上下文。 复制一个线程对象意味着创建两个对象来控制同一个系统线程的生命周期和同步点,这是逻辑上不允许的。
2. 并发和异步工具
类型 托管的资源 为什么不能复制?
std::mutex 互斥锁的底层系统资源。 如果复制,两个 mutex 对象将代表同一个锁,使得锁机制失效,无法保证互斥。
std::lock_guard / std::unique_lock std::mutex 的独占性锁定状态。 它们是 RAII 锁,复制会导致两个对象试图同时管理同一个锁,破坏了独占性。
std::promise 异步操作结果的共享状态 复制将导致两个 promise 实例可以对同一个共享状态设置结果,这会破坏"单次设置"的规则。
std::packaged_task 异步函数和其内部的 std::promise 它封装了 std::promise,因此也必须保证独占所有权,确保任务只被执行一次。
std::future 异步操作的获取句柄 虽然有些 future 实现可以复制(如 std::shared_future),但默认的 std::future 通常只能移动,因为它代表了对结果的独占性访问
3. C++20 同步原语
  • std::jthread :C++20 中的 RAII 线程,它自动 join,继承了 std::thread 不可复制的特性。

  • std::counting_semaphore / std::binary_semaphore:信号量的底层资源是独占的。

总结和设计原则

当你设计一个 C++ 类时,如果这个类管理着一个无法安全共享的底层资源(如操作系统句柄、网络套接字、文件描述符、内存块的所有权),那么你应该:

  1. 禁用拷贝构造函数和拷贝赋值运算符 (C++11/14/17 通常使用 = delete)。

  2. 实现移动构造函数和移动赋值运算符(将底层资源指针/句柄从源对象转移到目标对象,并清空源对象)。

通过这种设计,C++ 编译器强制执行了资源所有权的转移,保证了资源的生命周期安全,这是现代 C++ 编程中一个重要的设计范式。

相关推荐
2401_8920709821 小时前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei21 小时前
Visual Studio 配置C++opencv
c++·学习·visual studio
Wenweno0o21 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
chenjingming6661 天前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
cch89181 天前
Python主流框架全解析
开发语言·python
不爱吃炸鸡柳1 天前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发1 天前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
Momentary_SixthSense1 天前
设计模式之工厂模式
java·开发语言·设计模式
‎ദ്ദിᵔ.˛.ᵔ₎1 天前
STL 栈 队列
开发语言·c++
勿忘,瞬间1 天前
数据结构—顺序表
java·开发语言