右值引用和移动语义

c++11 增加了一个新的类型,右值引用,记作:&&

        左值是指在内存中有明确的地址,我们可以找到这块地址的数据(可取地址)。

        右值是只提供数据,无法找到地址(不可取地址)。//所有有名字的变量都是左值,而右值是匿名的。

一般情况下位于等号左边的是左值,位于等号右边的是右值,但是也可以出现左值给左值赋值的情况。

        c++11 中右值分为两种情况:一个是将亡值,另一个是纯右值。

                纯右值:非引用返回的临时变量,运算表达式产生的临时变量,原始字面量,lambda表达式等。

                将亡值:与右值引用相关的表达式,比如:T&&类型函数的返回值,std::move()的返回值

右值引用

        右值引用就是对右值的引用类型。因为右值是匿名的,所以我们只能通过引用的方式找到它无论是左值引用还是右值引用都必须被初始化,因为引用类型本身并不拥有所绑定对象的内存,只是该对象的一个别名。通过右值引用,该右值所占的内存又可以被找到并且使用。

右值引用的用处

        在 c++用对象初始化对象时会调用拷贝构造,如果这个对象占用堆内存很大,那么这个拷贝的代价就是非常大的,在某些情况,如果想要避免对象的深拷贝,就可以使用右值引用进行性能的优化。

class Test{
public:
    Test():num(new int(100)){
        cout<<"构造函数"<

        在上面的代码中添加了 移动构造函数(参数为右值引用类型),这样在进行 Test tgetObj();并没有调用构造函数进行深拷贝,而是调用的(浅拷贝)移动构造,提高了性能。

        本例子中,getObj()返回值是一个右值,在进行赋值操作的时候如果 等号 右边是一个右值,那么移动构造函数就会被调用。结论:需要动态申请大量的资源的类,应该设计移动构造,提高程序的效率。需要注意的是在提供移动构造的同时,一般也会提供左值引用拷贝构造函数,左值初始化新对象时会走拷贝构造。

右值引用特点

        c++中,并不是所有情况下&&都代表右值引用,在模板和自动类型推导(auto)中,如果是模板参数需要指定为 T&&,如果是自动类型推导需要指定为 auto &&,这两种情况下&&被称作 未定的引用类型。只另外 const T &&表示 一个右值引用,不是未定引用类型。

template
void fun(T&& param){ }
int main(){
    fun(10);//对于 f(10)来说传入的实参 10 是右值,因此 T&& 表示右值引用
    int x= 1;fun(x);//对于 f(x)来说传入的实参是 x 是左值,因此 T&& 表示左值引用
    return 0;
}

因为 T&& 或者 auto&&这种未定引用类型作为参数时,有可能被推导成右值引用,也有可能被推导为左值引用,在进行类型推导时右值引用会发生变化,这种变化被称作引用折叠。折叠规则如下:

        通过右值 推导 T&&或者 auto&& 得到的是一个右值引用类型,const T &&表示 一个右值引用

        通过左值(右值引用、左值、左值引用、常量右值引用、常量左值引用)推导 T&&或者auto&&得到的是一个左值引用类型

move

        c++11 添加了右值引用,却不能左值初始化右值引用,在一些特定的情况下免不了需要左值初始化右值引用(用左值调用移动构造),如果想要用左值初始化一个右值引用需要借助std::move()函数。move()函数可以将左值转换为右值。

移动语义(Move Semantics)

        C++11 引入的一项重要特性,它允许对象的资源(如堆上分配的内存)在不进行深度复制的情况下进行转移。通过移动语义,可以将对象的资源从一个对象转移到另-个对象,从而避免不必要的 内存拷贝只,提高程序性能和效率。

        如何提高性能:减少 内存分配只和释放的开销:在传统的拷贝语义中,每次对象被复制时都需要进行一次资源的分配和释放,而移动语义可以将资源的所有权从临时对象或右值对象直接转移到目标对象,避免了额外的内存分配和释放开销。

        避免不必要的数据复制:对于临时对象或右值对象,移动语义允许直接将资源所有权转移到目标对象,而不进行深度复制。这避免了不必要的数据复制,特别是对于大型数据结构或容器来说,能够显著提高程序的性能。

        提高容器的性能:在使用容器时,移动语义可以显著提高容器的性能。例如,在容器元素的插入、删除和返回操作中,通过移动语义可以避免不必要的数据复制和额外的内存分配开销,从而提高容器的性能和效率。

你可能感兴趣的:(c++)