C++11新特性:左值,右值,左值引用和右值引用

    C++11新引入了右值引用的概念。函數

        本質上來講,左值就是在內存中能夠尋址的對象(表現形式是能夠經過&操做符取指),而右值是在寄存器中或者內存中的匿名對象。對象

        左值能夠存在賦值運算符左右兩邊,但右值只能存在賦值運算符右邊(這有個例外,當一個類對象重載了負值運算符時,該類對象做爲右值也能夠存在賦值運算符左邊)。好比,生命週期

        int a = 0;         // a是左值內存

        2 = a;              // error, 2是匿名對象,是右值,不能放在賦值運算符左邊class

        a++ = 5;         // error,a++表達式返回的是直接數0,是個匿名對象,不能做爲左值,只能做爲右值語法

        ++a = 6;         // ok, ++a表達式返回的是對象a,所以能夠做爲左值(這點C++和傳統C語言有所不一樣)引用

 

        引用是對象的別名,引用分爲左值引用和右值引用。引用在聲明時就須要被賦值。error

        左值引用是對左值對象的引用,而且只能引用左值;而右值引用是對右值的引用,而且只能引用右值。一個右值表達式對象一般在表達式結束時即銷燬,而右值表達式被右值引用時,會延長右值表達式對象的生命週期,直到右值引用結束。static

        左值引用的語法以下:語言

        int a = 10;

        int &b = a;        // ok,左值引用聲明時初始化,引用一個左值表達式。

        int &c = 10;      // error,左值引用只能引用左值表達式,不能引用右值表達式。

        右值引用的語法以下:

        int a = 10;

        int &&b = a;    // error, 右值引用只能引用右值表達式,不能引用左值表達式。

        int &&c = 10;    // ok

    這裏有個須要注意的是:普通函數和類靜態成員函數的函數名既是左值,也是右值(即,函數名既能夠賦值給左值引用,也能夠賦值給右值引用)。以下:

void hello() {
    std::cout << "hello" << std::endl;
}

class CallBack {
public:
    CallBack();
    virtual ~CallBack();

    static void staticDump() {
        std::cout << "staticDump" << std::endl;
    }
};

int main() {
    typedef void(FuncType)();
    typedef void(FuncType1)(CallBack *);

    FuncType &func = hello;        // 普通函數hello函數名能夠做爲左值
    FuncType &&func1 = hello;    // 普通函數hello函數名能夠做爲右值
    func();
    func1();

    FuncType &funcStatic = CallBack::staticDump;        // 類靜態成員函數staticDump函數名能夠做爲左值
    FuncType &&funcStatic1 = CallBack::staticDump;    // 類靜態成員函數staticDump函數名能夠做爲右值
    funcStatic();
    funcStatic1();

    return 0;
}
    這裏,更進一步:函數名取地址是右值:

void func() {
    std::cout << "func" << std::endl;
}

typedef void (FuncType)();
typedef void (*FuncType1)();
int main() {
    int a = 10;

    FuncType &f1 = func;
    FuncType &&f2 = func;
    f1();
    f2();
    FuncType1 &f3 = &func;        //  錯誤,&func是右值,不能賦值給左值引用
    FuncType1 &&f4 = &func;    // ok, &func是右值,能夠賦值給右值引用

    f4();

    return 0; }     最後,不管是左值引用,右值引用函數名 或者 函數地址,均可以經過引用調用函數。

相關文章
相關標籤/搜索