C++11 右值引用和左值引用详解

C++11引用LValue/RValueReference

引用Reference

引用的声明:

T  &ref = object ;

T  & ref ( object ) ;

 

T  && ref = object ;

T  && ref ( object ) ;

 

引用声明时必须赋值

 

引用的有点类似于这种const类型的指针T *const t;

引用和指针一样,不会触发对象的构造函数和析构函数。

 

左值和右值LValue/RValue

按照字面意思理解:左值就是在赋值等于号左边的值,右值就是在右边的值。

左值和右值最好区别的是,左值是有变量名的,右值是没有变量名的,这些就是右值:常量“abcd”字符串,函数返回的临时对象。

 

 

左引用、右引用

左值引用声明:T & ref1;

右值引用声明:T && ref2;

引用本身是一个左值,因为它有名字,使用时ref1和ref2是相同的,当成普通变量使用。左值引用声明和右值引用声明后的变量都是一个引用,两者的区别在于,左值引用需要一个左值来赋值,指向左值;右值引用需要一个右值来赋值,指向右值

例如:

    int a;

    int &r11a;

    const int &r12 = 3;//const左值引用可以指向右值

 

    int &&r2 =a;//编译错误,无法指向左值

    int &&r3 = 3;//

    int (int &&a);

    f(r3);//编译错误,r3本身是左值

 

左值转右值

左值可以通过std::move转成右值,例如:

int &&r2=std::move(a);//std::move(a)会把 a 当成右值,这个语句于: int &r2 =a完全等效。

class A;

  A a;
A b = std::move(a); //会调用b的移动构造函数

 

移动构造函数

移动构造函数是使用右值引用类型当作参数的构造函数,如:

 

class A
{
public:
    int *p;

    A() :p(nullptr) {};
    A(int a)
    {
        p = new int(a);
    }

    A(const A& a) //复制构造函数
    {
        this->p = new int(*a.p);
    }

    A(A &&a) //移动构造函数
    {
        this->p = a.p;//因为a是一个右值,函数结束后a会被释放,
                      //所以可以直接拿使用a的内存,无需重新用new 分配。
        a.p = nullptr;
    }

    ~A()
    {
        if (nullptr != this->p)
        {
            delete p;
            this->p = nullptr;
        }
    }
};

 

 

因为右值一般都是临时变量,所以移动构造函数中无需再分配内存空间,可以直接使用右值中的内存,这样可以减少内存的分配次数和赋值次数。

 

任何函数都可以采用右值引用作为参数,例如:

void Fun (&&a)

{

}

 

模板中的引用参数

VS2015 中std::make_pair函数,只有以下一个定义:

template<class_Ty1class_Ty2>inline

    _CONST_FUNpair<typename_Unrefwrap<_Ty1>::type,

        typename_Unrefwrap<_Ty2>::type>

        make_pair(_Ty1 &&_Val1,_Ty2 &&_Val2)

    {   // return pair composed fromarguments

    typedefpair<typename_Unrefwrap<_Ty1>::type,

        typename_Unrefwrap<_Ty2>::type>_Mypair;

    return(_Mypair(_STDforward<_Ty1>(_Val1),

        _STDforward<_Ty2>(_Val2)));

    }

 

参数部分

    make_pair(_Ty1 &&_Val1_Ty2 &&_Val2)

似乎参数只可以使用右值进行赋值。但这个语句是可以编译通过的:

    int a;

    std::make_pair(a, 2);

 

VS2015 识别的类型

是如何推导到_Ty1&&  _Val1为左值呢?

 

引用的typedef

typedef int& lref;

typedef int&& rref;

int n;

lref& r1 = n; // type of r1 is int&

lref&& r2 = n; // type of r2 is int&

rref& r3 = n; // type of r3 is int&

rref&& r4 = 1; // type of r4 is int&&

 

除非类型为rref且用&&定义,才是右值引用类型。当lref用&&定义是还是左值引用。

 

 

所以上个例子中,_Ty1的类型为int&,所以make_pair的第一个值为左值

 

 

你可能感兴趣的:(编程语言杂记,C,11,右值引用,蓝天日记)