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++ 编程中一个重要的设计范式。

相关推荐
似水明俊德28 分钟前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
Thera7771 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
炘爚2 小时前
C语言(文件操作)
c语言·开发语言
阿蒙Amon2 小时前
C#常用类库-详解SerialPort
开发语言·c#
凸头2 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun3141592 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
君义_noip2 小时前
信息学奥赛一本通 1952:【10NOIP普及组】三国游戏 | 洛谷 P1199 [NOIP 2010 普及组] 三国游戏
c++·信息学奥赛·csp-s
Moksha2623 小时前
5G、VoNR基本概念
开发语言·5g·php
jzlhll1233 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
W.D.小糊涂3 小时前
gpu服务器安装windows+ubuntu24.04双系统
c语言·开发语言·数据库