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

相关推荐
C^h6 小时前
c++ string
开发语言·c++
raindayinrain6 小时前
c++高性能--原子操作,无锁编程,操作顺序
开发语言·c++·性能优化
学逆向的6 小时前
C++ 合并命名空间
开发语言·c++·网络安全
Zhao-Jichao6 小时前
VS2026 打包 C++ 程序生成 EXE,借助 Installer Project 扩展工具
开发语言·c++
学逆向的7 小时前
C 局部静态变量
c语言·开发语言·网络安全
小徐不徐说7 小时前
C++ 接口与插件设计:从工厂注册到 Qt 动态插件
数据库·c++·qt·系统架构·程序设计
大都督会赢的7 小时前
C++第一节课
开发语言·c++
UIU1147 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
“AI国潮设计-小江”7 小时前
【AIGC实战】Python+Stable Diffusion打造“英歌舞财神”IP,解锁“马到成功”等爆款情绪营销文案设计
开发语言·人工智能·python·prompt·aigc
小王C语言8 小时前
Qt常用控件:容器类控件,标题分组框、标签页(浏览器标签)
开发语言·qt