c11右值与移动语义

左值和右值:

左值具名,对应指定内存域,可访问;右值不具名,不对应内存域,不可访问;

临时对像是右值,左值可处于等号左边,右值只能放在等号右边,区分表达式的左右值属性有一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。

右值引用:

在 C++11 之前,右值是不能被引用的,最大限度就是用常量引用绑定一个右值,如 :const int &a = 1; 在这种情况下,右值不能被修改的。但是实际上右值是可以被修改的,既然右值可以被修改,那么就可以实现右值引用。C11增加的右值引用类型T &&,就是为了解决这一问题。

右值引用的作用:右值引用是用来支持转移语义的。转移语义可以将资源 ( 堆,系统对象等 ) 从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,能够大幅度提高 C++ 应用程序的性能。消除了临时对象的维护 ( 创建和销毁 ) 对性能的影响。

避免无意义复制
析构开销减少
当类的拷贝构造函数入参是右值时,可以避免复制和析构:

class A
{
public:
    A() :m_ptr(new int(0)){}
    A(const A& a):m_ptr(new int(*a.m_ptr)) //深拷贝的拷贝构造函数
    {
        cout << "copy construct" << endl;
    }
    A(A&& a) :m_ptr(a.m_ptr)
    {
        a.m_ptr = nullptr;
        cout << "move construct" << endl;
    }
    ~A(){ delete m_ptr;}
private:
    int* m_ptr;
};
int main(){
    A a = Get(false); 
}

引用折叠

引用折叠。通常,我们不能直接定义一个引用的引用,但是同过类型别名(使用typedef)和模板间接定义是可以的。当定义了引用的引用时,则这些引用形成了“折叠”,所有的情况下(除了一个例外),引用会折叠成一个普通的左值引用类型。这个例外就是右值引用的右值引用:

l X& &&、X& &&、X&& &都折叠成X&

l 类型X&& &&折叠成X&&

std::move

move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。 std::move

std::list< std::string > tokens;//省略初始化...
std::list< std::string > t = tokens; //存在拷贝
std::list< std::string > t2 = std::move(tokens); //不存在拷贝

如果不用std::move,拷贝的代价很大,性能较低。使用move几乎没有任何代价,只是转换了资源的所有权。如果一个对象内部有较大的对内存或者动态数组时,很有必要写move语义的拷贝构造函数和赋值函数,避免无谓的深拷贝,以提高性能。

std::forward

完美转发(perfect forwarding),是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。std::forward即是为转发而生,它会按照参数本来的类型来转发出去,不管参数类型是T&&这种未定的引用类型还是明确的左值引用或者右值引用。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值