当前位置: 首页 > article >正文

什么是C++的移动语义,它的作用什么?

移动语义(Move Semantics)是 C++11 引入的一项重要特性,它允许对象的资源(如堆上分配的内存)在不进行深度复制的情况下进行转移。通过移动语义,可以将对象的资源从一个对象转移到另一个对象,从而避免不必要的内存拷贝,提高程序性能和效率。

概念

右值和左值:

            左值: 有固定地址的对象,可以在赋值中出现在等号左侧(例如,变量)。

           右值: 临时对象或字面值,通常不能取地址,出现在赋值语句的右侧(例如,直接返回的结果)。

移动构造函数:

专门用于将临时对象的资源(例如动态分配的内存)“转移”到新对象上,而不是进行完整的复制。

移动赋值运算符:

用于在赋值时将右值的资源转移到左值,释放原有资源并接管右值的资源。

作用

  1. 提高性能: 移动语义允许程序员在对象的使用中避免不必要的深拷贝,从而提高性能。这在处理大型对象(如容器或复杂的数据结构)时尤为重要。

  2. 资源管理: 移动语义使得资源管理变得更加高效,特别是在涉及动态内存分配时。对象的生命周期可以更好地控制,避免内存泄漏和不必要的资源消耗。

  3. 简化代码: 移动语义简化了某些情况下的代码,特别是需要传递和返回大型对象时,代码更容易理解和维护。

示例

#include <iostream>  
#include <vector>  

class MyVector {  
public:  
    MyVector(size_t size) : data(new int[size]), size(size) {  
        std::cout << "Constructing MyVector of size " << size << std::endl;  
    }  
    
    // 移动构造函数  
    MyVector(MyVector&& other) noexcept : data(other.data), size(other.size) {  
        other.data = nullptr;  // 将原对象的指针设为空  
        other.size = 0;  
        std::cout << "Moving MyVector of size " << size << std::endl;  
    }  

    // 移动赋值运算符  
    MyVector& operator=(MyVector&& other) noexcept {  
        if (this != &other) {  
            delete[] data;  // 释放当前对象的内存  
            data = other.data; // 移动资源  
            size = other.size;  
            other.data = nullptr; // 将原对象的指针设为空  
            other.size = 0;  
            std::cout << "Moving assignment of MyVector of size " << size << std::endl;  
        }  
        return *this;  
    }  
    
    ~MyVector() {  
        delete[] data; // 释放资源  
        std::cout << "Destroying MyVector" << std::endl;  
    }  

private:  
    int* data;  
    size_t size;  
};  

int main() {  
    MyVector vec1(10);         // 构造一个对象  
    MyVector vec2 = std::move(vec1); // 移动构造  
    MyVector vec3(5);  
    vec3 = std::move(vec2);   // 移动赋值  
    
    return 0;  
}

输出: 

Constructing MyVector of size 10
Moving MyVector of size 10
Constructing MyVector of size 5
Moving assignment of MyVector of size 10
Destroying MyVector
Destroying MyVector
Destroying MyVector

解释一下上面的代码:

  • 1.构造函数MyVector(size_t size) 用于初始化类的对象。
    • data(new int[size]):动态分配一个大小为size的整数数组,并把其地址赋值给data指针。
    • size(size):初始化size成员变量。
    • 构造时输出一条信息,表示正在构造指定大小的MyVector对象。
  • 2.移动构造函数MyVector(MyVector&& other) noexcept
    • 该构造函数使用右值引用MyVector&&接受一个MyVector对象,允许“盗取”该对象的资源。
    • data(other.data):将other对象的data指针移动到当前对象。
    • size(other.size):将othersize赋给当前对象。
    • other.data = nullptr; 和 other.size = 0;:将other对象的资源指针设为nullptr,以避免意外访问释放后的内存。
    • 输出信息表示正在移动MyVector
  • 3.移动赋值运算符MyVector& operator=(MyVector&& other) noexcept
    • 与赋值操作符类似,但可以接收资源的右值引用。
    • if (this != &other):检查自我赋值,避免不必要的操作。
    • delete[] data;:释放当前对象data指针指向的内存,防止内存泄漏。
    • data = other.data; 和 size = other.size;:转移资源。
    • 设置other对象的资源为空,防止other被错误使用。
    • 输出信息,表示移动赋值。
  • main函数是程序的入口。
  • MyVector vec1(10);:创造一个大小为10的MyVector对象,这会调用构造函数。
  • MyVector vec2 = std::move(vec1);:通过std::movevec1转换为右值,并调用移动构造函数,将vec1的资源移动到vec2中。这会清空vec1的资源。
  • MyVector vec3(5);:创建一个大小为5的MyVector对象。
  • vec3 = std::move(vec2);:通过移动赋值,将vec2的资源移动到vec3中,此时vec2的资源被置空。

有什么问题话,大家可以留言并讨论。


http://www.kler.cn/a/408904.html

相关文章:

  • Windows系统运行库软件游戏修复工具
  • 【bug】使用transformers训练二分类任务时,训练损失异常大
  • 「Mac玩转仓颉内测版32」基础篇12 - Cangjie中的变量操作与类型管理
  • 【Redis_Day5】String类型
  • 【AI系统】GPU 架构回顾(从2018年-2024年)
  • 数据结构与算法——1122—复杂度总结检测相同元素
  • NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案
  • DataWhale—PumpkinBook(TASK05决策树)
  • 前端VUE项目启动方式
  • AI模型---安装cuda与cuDNN
  • 构建高效在线教育:SpringBoot课程管理系统
  • Windows用pm2部署node.js项目
  • 平面点排序(结构体专题)
  • SpringMVC的理解
  • 基于Springboot+微信小程序的社区论坛系统 (含源码数据库)
  • 推荐一个QDirStat基于 Qt 的目录统计工具
  • MyBatis基本使用
  • Jupyter 导入 - 国内安装 openai 和 python-dotenv 包
  • 实验室管理技术:Spring Boot技术的应用
  • 2025-2026财年美国CISA国际战略规划(下)
  • MySQL底层概述—1.InnoDB内存结构
  • 详细探索xinput1_3.dll:功能、问题与xinput1_3.dll丢失的解决方案
  • 2062:【例1.3】电影票(http://ybt.ssoier.cn:8088/problem_show.php?pid=2062)
  • transform学习
  • MongoDB相关问题
  • 汽车HiL测试:利用TS-GNSS模拟器掌握硬件性能的仿真艺术