C++ 新特性 筆記

摘錄

constexptr

C++14嚐鮮:constexpr函數(編譯期函數)ios

總結來講,就是在c++11以前,要實現編譯期數值計算須要繁瑣的模板元編程。在c++11 中,能夠是函數,在一句ruturn 語句中進行求值,函數中既不能有變量也不能有分之判斷語句,限制較多。在C++17以後,則取消了大部分限制,好比能夠有變量,能夠有分支判斷語句,但不能有goto,asm,try等語句。具體能夠參考cppreferencec++

準確的說,constexpr函數是一種在編譯期和運行期都能被調用並執行的函數。出於constexpr函數的這個特色,在C++11以後進行數值計算時,不管在編譯期仍是運行期咱們均可以統一用一套代碼來實現。編譯期和運行期在數值計算這點上獲得了部分統一。express

什麼是rvalues,lvalues,xvalues,glvalues和prvalues?

  • lvalue(所謂的,歷史上,由於左值能夠出如今賦值表達式的左側)表示一函數或一個對象。 [示例:若是E是指針類型的表達式,則*E 是一個左值表達式,引用要指向的對象或函數E 。另外一個例子,調用返回類型爲左值引用的函數的結果是左值。
  • xvalue(一個「到期」值)也指一個對象,一般接近其壽命的末尾(使得其資源能夠被移動,例如)。xvalue是涉及rvalue引用的某些表達式的結果。 [示例:調用返回類型爲右值引用的函數的結果是xvalue。]
  • glvalue (「廣義」左值)是左值 或x值。
  • rvalue(所謂的,歷史上,由於右值能夠出如今賦值表達式的右手側)是x值,臨時對象或子對象,或它們的不與一個對象相關聯的值。
  • prvalue(「純」右值)是一個rvalue,這不是一個x值。 [示例:調用返回類型不是引用的函數的結果是prvalue]

lvalue 左值

當且僅當E指的是已經具備使其可在E外部訪問的標識(地址,名稱或別名)的實體時,表達式E屬於左值類別。編程

#include <iostream>

int i=7;

const int& f(){
    return i;
}

int main()
{
    std::cout<<&"www"<<std::endl; // This address ...
    std::cout<<&"www"<<std::endl; // ... and this address are the same.
    "www"; // The expression "www" in this row is an **lvalue expression**, because it refers to the same entity ...
    "www"; // ... as the entity the expression "www" in this row refers to.

    i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression i in this row refers to.

    int* p_i=new int(7);
    *p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
    *p_i; // ... as the entity the expression *p_i in this row refers to.

    const int& r_I=7;
    r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
    r_I; // ... as the entity the expression r_I in this row refers to.

    f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression f() in this row refers to.

    return 0;
}

xvalues 亡值

若表達式E屬於xvalue類別,當且僅當它知足:
-不管是隱式調用仍是顯示調用,調用一個函數的結果返回一個對要返回的對象類型的引用的rvalue函數

int&& f(){
    return 3;
}

int main()
{
    f(); // 表達式 f() 是xvalue ,由於 f() 的返回類型是一個對象類型的引用的 rvalue.

    return 0;
}

-或者,右值(rvalue)引用對象類型的castui

int main()
{
    static_cast<int&&>(7); // 表達式static_cast<int&&>(7) , 其是右值引用對象類型的 cast.
    std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).

    return 0;
}

-類成員訪問表達式指定 非引用類型的非靜態數據成員, 其中對象表達式是 xvaluethis

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f().i; //  f().i  是 xvalue, 由於 As::i 是 non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.

    return 0;
}
  • 一種pointer-to-member表達式, 其中第一個操做數是 xvalue, 第二個操做數是指向數據成員的指針。
    請注意,上述規則的效果是對命名rvalue引用被視爲lvalues,對對象的未命名rvalue引用被視爲xvalues; 對函數的右值引用被視爲左值,不管是否命名。
#include <functional>

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
    As&& rr_a=As();
    rr_a; //  rr_a 是 lvalue category,由於它指的是一個命名的 rvalue 對象引用
    std::ref(f); // n std::ref(f) 表達式是 lvalue , 由於它指的是一個命名的 rvalue 對象引用

    return 0;
}

prvalue

當且僅當E既不屬於左值也不屬於xvalue類別時,表達式E屬於prvalue類別。.net

struct As
{
    void f(){
        this; // this  是 **prvalue** 表達式。 注意:this 不是一個變量
    }
};

As f(){
    return As();
}

int main()
{
    f(); // f() 表達式屬於 prvalue category, 其既不屬於 lvalue 也不屬於 xvalue 類

    return 0;
}

rvalue

當且僅當E屬於xvalue類別或屬於prvalue類別時,表達式E屬於rvalue類別。
請注意,此定義表示當且僅當E指的是沒有任何標識使其可在E以外訪問的實體時,表達式E屬於右值類別。指針

glvalues

當且僅當E屬於lvalue類別或xvalue類別時,表達式E屬於glvalue類別。c++11

一個實用的規則
Scott Meyers 已出版的經驗的一個很是有用的規則,從左值右值的區別。

若是能夠獲取表達式的地址,則表達式爲左值。 若是表達式的類型是左值引用(例如,T&或const T&等),則該表達式是左值。 不然,表達式是右值。從概念上(一般也是實際上),rvalues對應於臨時對象,例如從函數返回的或經過隱式類型轉換建立的臨時對象。大多數文字值(例如,10和5.3)也是右值。

相關文章
相關標籤/搜索