C++ Copy Control笔记(2):Moving Object

文章介绍了C++中的Move语义,用于优化那些在复制后即将被删除的对象。Move涉及到左值和右值的概念,以及左值引用和右值引用。通过std::move函数,可以将左值转换为右值引用,然后利用移动构造器和移动赋值运算符有效地转移资源,避免不必要的拷贝开销。移动操作后,原对象可能处于不确定状态,应避免进一步使用。
摘要由CSDN通过智能技术生成

为什么使用Move而不是Copy

在一些我们需要进行复制操作的代码语句中,被复制的对象在被复制后很快就被删除不再使用了,在这种情况下,拷贝一份数据显然产生了不必要的开销,因此便产生了对移动数据的需求。

前置知识:左值右值

左值与右值

笼统的来说,左值即可以放到等号左边的东西,而右值是只能放在等号右边的东西,C++中,我们可以获取左值的地址而无法获取右值的地址

通常,我们自己定义的变量都是左值。左值一般都是需要长期存在的(变量可以进行后续操作),而右值的生命周期是短暂的,理应在一次调用后便销毁(eg. a = 4, 我们不会关心4是否存在内存中,或是存在什么位置)

eg. 在下面的代码中,a,b,c均为左值,而4为右值,我们无法写做4 = a

int a = b + c;
int a = 4;

左值引用和右值引用

C++中,我们常常使用&来表示一个变量为引用类型,这种引用通常被称为左值引用,顾名思义,左值引用引用的对象应该是一个左值。其中有一个例外,若引用被定义为一个常值,则它可以作为一个右值的引用。

相对应的,C++11引入了右值引用,用&&来表示,这种引用的对象只可为右值。

eg.

int a = 0
int& b = a;    ok
int& c = 5;    error: 左值引用不可引用右值
int&& d = a;    error: 右值引用不可引用左值
int&& e = 5;    ok
const int& f = 5;    ok: 常值引用可以引用右值

C++库中的move方法

在C++中,如果我们想将一个左值作为一个右值来进行操作,我们可以调用std::move方法,在进行move操作后,我们不保证被移动的变量的后续情况如何

int a = 1;
int&& rr = std::move(a);

移动构造器和移动赋值运算符

为了对我们自己构造的类使用移动操作,我们需要自己构造移动构造器和移动赋值运算符。移动操作类似与拷贝操作,但不同的是,移动到的对象会将被移动的对象的资源"偷走"在进行了移动操作后,应保证不再访问被移动的对象,此外还需保证被移动对象可以被安全的删除而不影响到其他对象

移动构造器

移动构造器传入的参数是一个右值引用(暗示了被引用的对象是临时的,后续不再使用)

eg. StrVec的移动构造器将原先对象的指针都赋值到了新的对象中,并将原先对象的指针设为了空值,确保原先对象能正常被删除

StrVec::StrVec(StrVec &&s) noexcept // move won't throw any exceptions
 // member initializers take over the resources in s
 : elements(s.elements), first_free(s.first_free),
cap(s.cap)
{
 // leave s in a state in which it is safe to run the destructor
 s.elements = s.first_free = s.cap = nullptr;
}

移动赋值运算符

类似于移动构造器,移动赋值运算符传入的参数也是一个右值引用。同时,类似与拷贝赋值运算符的是,我们需要保证自己移动到自己时的可用性。

StrVec &StrVec::operator=(StrVec &&rhs) noexcept
{
    // direct test for self-assignment
    if (this != &rhs) {
        free(); // free existing elements
        elements = rhs.elements; // take over resources from rhs
         
        first_free = rhs.first_free;
        cap = rhs.cap;
        // leave rhs in a destructible state
        rhs.elements = rhs.first_free = rhs.cap = nullptr; 
    } 
    return *this;
}

Reference

C++ Primer, 5th Edition

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值