std::move资源转移的具体实现原理

move语义可以实现资源的所有权转移而非拷贝,是如何实现的?又在何时有用?

实际上这里的资源转移具体分为两步实现:1、move函数改为右值。2、调用右值构造或赋值函数。真正能否实现资源转移取决于第二步。

步骤

move函数改为右值

move函数只是单纯的将一个变量改为右值而已,实际上没有任何其他逻辑。

右值构造/赋值

在某个类中,除了实现了默认的构造/赋值函数,还会实现一个专门用于右值的构造/赋值函数(重载)。这个函数的传入参数就是右值(&&),也就是说前一步的move函数只是为了触发这个右值的重载版本而已。

STL的容器本身支持move,以下就以vector为例。

vector<int>va(10);
cout<<va.begin().base()<<endl;//0x209af8164f0

vector<int>vb(std::move(va));//移动构造
cout<<va.begin().base()<<" "<<vb.begin().base()<<endl;//0 0x209af8164f0

vector<int>vc(vb);//直接构造
cout<<vb.begin().base()<<" "<<vc.begin().base()<<endl;//0x2c4d28164f0 0x2c4d2816520

可以看到如果使用move来构造,va的begin会被直接置0,而vb的begin则变成了原有va的begin。这里实现了原有资源内存不变的情况下所有权由va转移到vb。

而如果不使用move构造(vc),会直接开辟一块新的地址来存储新的vector。

自定义类的move

一个自定义类,c++会内部默认实现一个move,对于类内的支持move的成员变量调用move,其余的则是普通拷贝。

class A{
public:
    size_t sz;
    vector<int>nums;
    explicit A(size_t size){
        sz = size;
        nums.resize(size);
    }
};
int main()
{
    A a(10);
    A b(std::move(a));
    cout<<a.sz<<" "<<a.nums.size()<<endl;
    cout<<b.sz<<" "<<b.nums.size()<<endl;
}

/*输出如下
10 0
10 10
*/

可以看到,在类A中定义了一个size_t(不支持move)和一个vector(支持move)。这种情况下如果使用c++自己生成的右值构造函数,会把sz直接拷贝而nums实现了资源转移(a中的nums已经清空了)。

不过也可以自定义右值构造/赋值函数。

class A{
public:
    size_t sz;
    vector<int>nums;
    explicit A(size_t size){
        sz = size;
        nums.resize(size);
    }
    A(A&& other)noexcept{
        sz=other.sz;
        nums=std::move(other.nums);
        other.sz=0;
    }
};

/*
0 0
10 10
*/

这个A类就自定义实现了一个右值构造覆盖了原本的默认右值构造,可以实现整个类的资源转移(sz和nums的值都被move走了,原本的变量都清空)。

何时有用?

只有在存在资源所有权的变量中才有用。

如果是普通的int、double类型,move实际上就是单纯的拷贝,清空原本数据本身就是一个负担,没必要操作。

如果存在一个指针,move就有意义了,因为move的时候可以在不改变原有地址内容和不开辟新内存的情况下,让另一个指针指向这个资源并清空原本的指针。

就像vector中,本身vector只是持有一块连续内存的begin、size、end等属性,在实际move的时候只需要把这些属性(而非全部内存内容)告诉其他对象即可,其他对象也就相当于持有这部分内存。这时候只需要再清空原本指针就实现了资源转移。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值