zoukankan      html  css  js  c++  java
  • 【转】int && 非常量右值

    C++ 11中引入的右值引用正好可用于标识一个非常量右值。C++ 11中用&表示左值引用,用&&表示右值引用,如:

    int &&a = 10

    右值引用根据其修饰符的不同,也可以分为非常量右值引用和常量右值引用。

    C++ 11中引入的一个非常重要的概念就是右值引用。理解右值引用是学习“移动语义”(move semantics)的基础。而要理解右值引用,就必须先区分左值与右值。

    对左值和右值的一个最常见的误解是:等号左边的就是左值,等号右边的就是右值。左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象。一个区分左值与右值的便捷方法是:看能不能对表达式取地址,如果能,则为左值,否则为右值。下面给出一些例子来进行说明。

    1 int a = 10  
    2 int b = 20  
    3 int *pFlag = &a;  
    4 vector<int> vctTemp;  
    5 vctTemp.push_back(1);  
    6 string str1 = "hello "  
    7 string str2 = "world"  
    8 const int &m = 1  

    请问,a,b, a+b, a++, ++a, pFlag, *pFlag, vctTemp[0], 100, string("hello"), str1, str1+str2, m分别是左值还是右值?

    a和b都是持久对象(可以对其取地址),是左值;

    a+b是临时对象(不可以对其取地址),是右值;

    a++是先取出持久对象a的一份拷贝,再使持久对象a的值加1,最后返回那份拷贝,而那份拷贝是临时对象(不可以对其取地址),故其是右值;

    ++a则是使持久对象a的值加1,并返回那个持久对象a本身(可以对其取地址),故其是左值;

    pFlag和*pFlag都是持久对象(可以对其取地址),是左值;

    vctTemp[0]调用了重载的[]操作符,而[]操作符返回的是一个int &,为持久对象(可以对其取地址),是左值;

    100和string("hello")是临时对象(不可以对其取地址),是右值;

    str1是持久对象(可以对其取地址),是左值;

    str1+str2是调用了+操作符,而+操作符返回的是一个string(不可以对其取地址),故其为右值;

    m是一个常量引用,引用到一个右值,但引用本身是一个持久对象(可以对其取地址),为左值。

    区分清楚了左值与右值,我们再来看看左值引用。左值引用根据其修饰符的不同,可以分为非常量左值引用和常量左值引用。

    非常量左值引用只能绑定到非常量左值,不能绑定到常量左值、非常量右值和常量右值。如果允许绑定到常量左值和常量右值,则非常量左值引用可以用于修改常量左值和常量右值,这明显违反了其常量的含义。如果允许绑定到非常量右值,则会导致非常危险的情况出现,因为非常量右值是一个临时对象,非常量左值引用可能会使用一个已经被销毁了的临时对象。

    常量左值引用可以绑定到所有类型的值,包括非常量左值、常量左值、非常量右值和常量右值。

    (1)非const左值引用只能绑定到非const左值;
    (2)const左值引用可绑定到const左值、非const左值、const右值、非const右值;
    (3)非const右值引用只能绑定到非const右值;
    (4)const右值引用可绑定到const右值和非const右值。

    大致意思是:模板参数的推导其实就是形参和实参的比较和匹配,如果形参是一个引用类型(如P&),那么就使用P来做类型推导;如果形参是一个cv-unqualified(没有const和volatile修饰的)右值引用类型(如P&&),并且实参是一个左值(如类型A的对象),就是用A&来做类型推导(使用A&代替A)。

    template <class _Tp> void f(_Tp &&amp ;) { /* do something */ }
    template <class _Tp> void g(const _Tp &&amp ;) { /* do something */ }
    int x = 123;
    f(x);   // ok,f()模板函数形参为非const非volatile右值引用类型,实参x为int类型左值,使用int&来做参数推导,因此调用f<int &>(int &amp ;)
    f(456); // ok,实参为右值,调用f<int>(int &&amp ;)
    g(x);   // error,g()函数模板参数为const右值引用类型,会调用g<int>(const int &&amp ;),通过右值引用规则四可知道,const右值引用不能绑定到左值,因此会导致编译错误

    原文地址:http://blog.csdn.net/yuanwang1986/article/details/8666459

  • 相关阅读:
    SCAU 9504 面试
    SCAU 9503 懒人选座位
    SCAU 8628 相亲
    SCAU 10691 ACM 光环
    SCAU 8626 原子量计数
    SCAU 10674 等差对
    HDU ACM 1048 The Hardest Problem Ever (水题)
    SCAU 9502 ARDF
    SCAU 10686 DeathGod不知道的事情
    SCAU 8629 热身游戏(高精度)
  • 原文地址:https://www.cnblogs.com/davygeek/p/4211566.html
Copyright © 2011-2022 走看看