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

相关推荐
Marst Code1 小时前
Python 3.9 已停止维护!从 3.9 到 3.14 全版本深度对比,生产环境该选哪个?
开发语言·python
ZJH__GO1 小时前
网络编程v2--多客户端互通
java·运维·服务器·开发语言·计算机网络
zhangfeng11332 小时前
Ascendc 大语言模型框架 AscendCraft 和pypto 的区别 pypto生成算子c++源码吗
c++·人工智能·语言模型·算子开发
万岳科技系统开发2 小时前
智慧医院小程序开发推动医疗服务流程全面线上化
大数据·开发语言·人工智能
一只小灿灿2 小时前
C++ 修饰符全面详解
开发语言·c++
马里马里奥-2 小时前
从零搭建AI Agent工具链的技术文章大纲
开发语言·qt
code_pgf2 小时前
C/C++ 中 `typedef` 关键字详解
c语言·c++
不做Java程序猿好多年3 小时前
Java中 String、StringBuffer、StringBuilder 的区别详解
开发语言·python
会周易的程序员3 小时前
js-shm: 高性能 Node.js 共享内存模块
开发语言·javascript·c++·node.js·共享内存·shm
笨蛋不要掉眼泪3 小时前
Java虚拟机:常用参数
java·开发语言·python