C++移动语义(右值引用,移动构造函数,移动赋值函数)

在什么样的背景下提出来的?

在程序运行过程中,会产生大量临时对象,临时对象只在某一个表达式执行的过程中创建,执行完毕时,临时对象被马上销毁。本质上只是用来进行过度的,这种带来了资源拷贝上的不必要的浪费。特别是当对象包含大量数据时

移动语义通过引入移动构造函数和移动赋值运算符,可以避免不必要的深拷贝,大幅提高程序的性能。

需求

我们希望临时对象在拷贝时能直接转移到新对象中。

解决方案

C++11提出了右值引用

左值与右值的概念

左值:可以取地址

右值:不可以取地址。包括临时变量、临时对象(string("world"))、字面值常量。

左值引用与右值引用

左值引用:左值引用可以绑定到左值,但不能绑定到右值。

int &ref= a;
int &ref=10;//error

const左值引用:const左值引用既可以绑定到左值,也可以绑定到右值

const int &ref=a;
const int &ref=10;

 右值引用:右值引用可以绑定到右值,但不能绑定到左值

int &&ref=10
int &&ref=a;//error

类中增加2个函数

1,具有拷贝控制语义的函数

拷贝构造函数,赋值运算符函数

2,具有移动语义的函数

1)移动构造函数与移动赋值运算符函数,编译器不会自动提供,必须要手写

2)针对右值而言,移动构造函数优先于拷贝构造函数的执行

3)深拷贝—>浅拷贝

移动构造函数
class String
{
public:
    String()
    : _pstr(nullptr)
    {
        cout << "String()" << endl;
    }

    //针对于右值而言,移动构造函数优先于拷贝构造函数的执行
    //
    //移动构造函数,移动语义,
    //将String("world")申请的堆空间直接转移给s3的数据成员_pstr
    //String s3 = String("world")
    String(String &&rhs)
    : _pstr(rhs._pstr)
    {
        cout << "String(String &&)" << endl;
        rhs._pstr = nullptr;
    }

    ~String()
    {
        cout << "~String()" << endl;
        if(_pstr)
        {
            delete [] _pstr;
            _pstr = nullptr;
        }
    }

private:
    char *_pstr;
};
移动赋值运算符函数
#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

class String
{
public:
    String()
    : _pstr(nullptr)
    {
        cout << "String()" << endl;
    }

    //赋值运算符函数
    String &operator=(const String &rhs)
    {
        cout << "String &operator=(const String &)" << endl;
        if(this != &rhs) //1、防止自复制
        {
            delete [] _pstr;//2、释放左操作数
            _pstr = nullptr;

            _pstr = new char[strlen(rhs._pstr) + 1]();//3、深拷贝
            strcpy(_pstr, rhs._pstr);
        }

        return *this;//4、返回*this
    }

    /* s2 = std::move(s2); */
    //移动赋值运算符函数
    //s2 = String("world")
    String &operator=(String &&rhs)
    {
        cout << "String &operator=(String &&)" << endl;
        if(this != &rhs) //1、防止自移动
        {
            delete [] _pstr;//2、释放左操作数
            _pstr = nullptr;

            _pstr = rhs._pstr;//3、浅拷贝
            rhs._pstr = nullptr;
        }

        return *this;//4、返回*this
    }

    ~String()
    {
        cout << "~String()" << endl;
        if(_pstr)
        {
            delete [] _pstr;
            _pstr = nullptr;
        }
    }

private:
    char *_pstr;
};

总结

左右值的概念,左值引用右值引用的概念。

拷贝构造函数与赋值运算符函数,编译器会自动提供;但是移动构造函数与移动赋值运算符函数,编译器不会自动提供,必须要手写。

将拷贝构造函数与赋值运算符函数称为具有拷贝控制语义的函数;将移动构造函数与移动赋值运算符函数称为具有移动语义的函数。

移动语义的函数优先于拷贝语义的函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值