移动语义 in C++【C++学习笔记】

本文介绍了C++11引入的移动语义,如何通过移动构造函数简化对象传递,避免不必要的内存复制,尤其是在处理复杂对象和堆分配时提升性能。通过String类实例详细展示了移动构造函数的使用和其在内存效率上的优势。
摘要由CSDN通过智能技术生成

89.移动语义 in C++

当我们知道左值和右值,左值引用和右值引用后,我们可以看看它们最大的一个用处:移动语义

🍅移动语义概述

移动语义让事情变得简单,移动语义本质上允许我们移动对象。这在C++11前是不可能的,因为C++11引入了右值引用,这是移动语义所必须的

其基本思想是:当写C++代码时,很多情况下,我们不需要或者不想把一个对象从一个地方复制到另一个地方,但又不得不复制。

  • 例如,把一个对象传给一个函数,那么它就要获得那个对象的所有权,我别无选择,只能拷贝。而当想从一个函数返回一个对象时也是如此,我仍然需要在函数中创建那个对象,然后返回它,也就是说我又要复制数据了

当然如果对象仅仅是由一对整数或者类似的东西组成,复制似乎无妨。但是如果里面有堆分配这种东西,那么就会大幅降低速度了。而这便是移动语义的用武之处了。如果我们只是移动对象而不是复制他,那么性能会更高

来点例子

注意下面的String假设是自己弄出来的字符串类

class Entity {
public:
    Entity(const String& name) 
        : m_Name(name) {}
    void PrintName() {
        std::cout << m_Name << "\n";
    }
private:
    String m_Name;
};

int main() {
    Entity a("Cherno");	//本质上是Entity a(String("Cherno"));	这里将"Cherno"视为左值
    a.PrintName();
}

就上面这么简单的构建一个对象的操作,便分配了两次内存

  • 首先在main函数的作用域中创建了一个"Cherno"的临时字符串,然后将其传入Entity的构造函数
  • 然后在构造函数中,将这个临时字符串复制给了m_Name

那么为什么不能在main函数中分配,然后把它移动到m_Name里呢?这就用到了移动语义了

🍅移动语义的使用

如上个例子,我们需要写一个move构造函数,这和复制构造函数很类似。

move构造函数接受的是一个右值,即临时值

即在Entity a("Cherno");中,将"Cherno"不再视为左值,它只是作为Entity构造函数的一个参数

noexcept 指定符

含义:指定函数是否抛出异常。

举例:void f() noexcept {}; // 函数 f() 不抛出异常

String(String &&other) noexcept {
	
}

通过指定这个构造函数,希望最终执行那个”复制“时,不会复制,而变成移动

💡而为了让他能工作,还要确保Entity有一个构造函数能够接受一个临时值!

  • 这里还要用std::move来显示转换name成临时值,才可以调用move构造函数!才能让具体构造出来的对象是临时值右值!!!(怎么字符串这么多事的)
Entity(String &&name)
    : m_Name(std::move(name)) {}

正式书写move构造函数,与原来复制构造函数不同的是:只是简单的给指针赋值

(注意这里的m_Data是一个指针!)

//下面是String类的复制构造函数
String(const String &other) {
    m_Size = other.m_Size;	//记录字符串大小,不用理会
    m_Data = new char[m_Size];
    memcpy(m_Data, other.m_Data, m_Size);
}
//下面是String类的move构造函数
String(String &&other) noexcept {	//注意这里是右值引用!!! 
    m_Size = other.m_Size;	
    m_Data = other.m_Data;	//不同之处
    //这里便完成了数据的转移,将other里的数据偷走了
    other.m_Size = 0;
    other.m_Data = nullptr;
}

💡两步操作:让新对象的指针指向指定内存,然后将旧对象的指针移开

所以这里做的其实是接管了原来旧的内存,而不是将这片内存复制粘贴!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值