0

0

c++怎么实现一个只可移动(movable)不可复制(copyable)的类_C++对象语义设计与移动优化

尼克

尼克

发布时间:2025-11-11 20:12:02

|

499人浏览过

|

来源于php中文网

原创

答案:通过删除拷贝构造函数和赋值运算符并默认或自定义移动操作,可实现只可移动类;继承非复制基类可复用逻辑;移动时需转移资源、置空原对象并标记noexcept以优化性能。

c++怎么实现一个只可移动(movable)不可复制(copyable)的类_c++对象语义设计与移动优化

在C++中设计一个只可移动(movable)、不可复制(non-copyable)的类,是现代C++资源管理和对象语义设计中的常见需求。这类类通常用于管理独占资源,如动态内存、文件句柄、网络连接等,确保同一时间只有一个对象拥有该资源。

禁用拷贝构造和拷贝赋值

要让一个类不可复制,最直接的方法是显式删除拷贝构造函数和拷贝赋值运算符:

class MovableOnly {
public:
    MovableOnly() = default;
// 禁止复制
MovableOnly(const MovableOnly&) = delete;
MovableOnly& operator=(const MovableOnly&) = delete;

// 允许移动
MovableOnly(MovableOnly&&) = default;
MovableOnly& operator=(MovableOnly&&) = default;

~MovableOnly() = default;

};

通过 = delete 显式禁用复制操作,编译器将拒绝任何尝试复制该类实例的代码。这是实现不可复制语义的标准方式。

立即学习C++免费学习笔记(深入)”;

继承自 std::enable_if 或使用基类辅助

如果你有多个类都需要不可复制语义,可以定义一个通用的不可复制基类:

class NonCopyable {
protected:
    NonCopyable() = default;
    ~NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;

};

class MovableOnly : private NonCopyable { // ... };

这种设计广泛用于标准库和第三方库中(如 boost::noncopyable),避免重复代码。

确保移动操作的安全与高效

只允许移动并不自动意味着性能优化。你需要确保移动构造函数和移动赋值运算符真正“转移”资源,而不是退化为深拷贝。

超级简历WonderCV
超级简历WonderCV

免费求职简历模版下载制作,应届生职场人必备简历制作神器

下载

例如,管理一个动态数组的类:

class Buffer {
    char* data_ = nullptr;
    size_t size_ = 0;

public: explicit Buffer(sizet size) : data(new char[size]), size_(size) {}

~Buffer() { delete[] data_; }

Buffer(const Buffer&) = delete;
Buffer& operator=(const Buffer&) = delete;

Buffer(Buffer&& other) noexcept 
    : data_(other.data_), size_(other.size_) {
    other.data_ = nullptr;
    other.size_ = 0;
}

Buffer& operator=(Buffer&& other) noexcept {
    if (this != &other) {
        delete[] data_;
        data_ = other.data_;
        size_ = other.size_;
        other.data_ = nullptr;
        other.size_ = 0;
    }
    return *this;
}

};

关键点:

  • 移动构造函数接收右值引用(T&&)
  • 移动后源对象应进入合法但可析构的状态(通常置空指针)
  • 标记为 noexcept,这对STL容器性能至关重要

移动语义与RAII结合的优势

只可移动类天然适合RAII(资源获取即初始化)模式。资源在其生命周期内被唯一持有,移动时转移所有权,避免了引用计数或锁的开销。

例如,std::unique_ptr 就是典型的只可移动类型。你可以安全地在函数间传递它,而不会意外复制底层指针。

当你设计类似智能指针、句柄封装、临时缓冲区等类型时,优先考虑只可移动语义,能显著提升程序的安全性和效率。

基本上就这些。正确使用删除默认函数、实现移动操作并注意资源转移细节,就能写出高效且安全的只可移动类。不复杂但容易忽略的是 noexcept 和资源清理状态的维护。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1435

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

224

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

456

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

6

2025.12.06

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

20

2025.11.16

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

266

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

207

2023.12.29

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

62

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 5.7万人学习

C 教程
C 教程

共75课时 | 3.8万人学习

C++教程
C++教程

共115课时 | 10.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号