天天看點

關鍵字:decltype、constexpr、typename、class/函數:boolalpha

關鍵字:decltype

decltype操作符的值是一個類型,可用于其它對象的聲明

例如:

double a =0.0;

decltype(a) b =1.0;//b is a double

可用于不知道變量類型的時候,或者變量類型名稱過長,比如疊代器類型。

*decltype隻在編譯期計算表達式的類型,不在運作期計算表達式的值

例如:

decltype(a++) c = 3.8; // c is a double

decltype的操作的是函數表達式:則傳回該函數傳回值的類型

int a =123,b=234;

decltype(max(&a,&b)) c;

用于獲得lambda表達式的類型

下面的cmp就是一個lambda對象,而lambda對象的類型一般很難寫出,而在定義一個set對象的時候,又需要給出cmp的類型,是以這裡用decltype來擷取。

auto cmp = [](const Person& p1,const Person& p2){

return p1.lastname()<p2.lastname() ||

(p1.lastname() == p2.lastname() &&

p1.firstname()<p2.firstname());

};

面對lambda,我們手上往往隻有object,沒有type。要獲得type就得借助于decltype.

關鍵字:constexpr

constexpr是C++11中新增的關鍵字,其語義是“常量表達式”,也就是在編譯期可求值的表達式。

constexpr所修飾的變量一定是編譯期可求值的,所修飾的函數在其所有參數都是constexpr時,一定會傳回constexpr。

constexpr int Inc(int i) {

return i + 1;

}

constexpr int a = Inc(1); // ok

constexpr int b = Inc(cin.get()); // !error

constexpr int c = a * 2 + 1; // ok

constexpr的好處:

是一種很強的限制,更好地保證程式的正确語義不被破壞。

編譯器可以在編譯期對constexpr的代碼進行非常大的優化,比如将用到的constexpr表達式都直接替換成最終結果等。

相比宏來說,沒有額外的開銷,但更安全可靠。

函數:boolalpha

boolalpha是頭檔案#include 中的一個函數,是把bool a = 1;

變量列印出false或者true的函數:

使用如下:

#include

using namespace std;

int main()

{

bool a = 0;

cout<<“請為布爾變量a指派:(0 OR !0)”<<endl;

cout<<"=分隔符=="<<endl;

cout<<“若輸入0則列印false,輸入其他的數字均顯示true:\n”<<endl;

cin>>a;

cout<<boolalpha<<a<<endl;

cout<<"=分隔符=="<<endl;

return 0;

}

關鍵字:decltype、constexpr、typename、class/函數:boolalpha

關鍵字:typename與class

在 C++ Template 中很多地方都用到了 typename 與 class 這兩個關鍵字,而且好像可以替換,是不是這兩個關鍵字完全一樣呢?

相信學習 C++ 的人對 class 這個關鍵字都非常明白,class 用于定義類,在模闆引入 c++ 後,最初定義模闆的方法為:

template…

這裡 class 關鍵字表明T是一個類型,後來為了避免 class 在這兩個地方的使用可能給人帶來混淆,是以引入了 typename 這個關鍵字,它的作用同

class 一樣表明後面的符号為一個類型,這樣在定義模闆的時候就可以使用下面的方式了:

template…

在模闆定義文法中關鍵字 class 與 typename 的作用完全一樣。

typename 難道僅僅在模闆定義中起作用嗎?其實不是這樣,typename 另外一個作用為:使用嵌套依賴類型(nested depended name),如下所示:

class MyArray

{

public:

typedef int LengthType;

}

template

void MyMethod( T myarr )

{

typedef typename T::LengthType LengthType;

LengthType length = myarr.GetLength;

}

這個時候 typename 的作用就是告訴 c++ 編譯器,typename 後面的字元串為一個類型名稱,而不是成員函數或者成員變量,這個時候如果前面沒有typename,編譯器沒有任何辦法知道 T::LengthType 是一個類型還是一個成員名稱(靜态資料成員或者靜态函數),是以編譯不能夠通過。

template struct X {};

template struct Y

{

// X可以查找到原型;

// X是一個依賴性名稱,模闆定義階段并不管X是不是正确的。

typedef X ReboundType;

// X可以查找到原型;
// X<T>是一個依賴性名稱,X<T>::MemberType也是一個依賴性名稱;
// 是以模闆聲明時也不會管X模闆裡面有沒有MemberType這回事。
typedef typename X<T>::MemberType MemberType2;

// UnknownType 不是一個依賴性名稱
// 而且這個名字在目前作用域中不存在,是以直接報錯。
// typedef UnknownType MemberType3;    

void foo()
{
    X<T> instance0;
    typename X<T>::MemberType instance1;
}
           

};

左值和右值

左值是代表一個記憶體位址值,并且通過這個記憶體位址,就可以對記憶體進行讀并且寫(主要是能寫)操作;這也就是為什麼左值可以被指派的原因了。相對應的還有右值:當一個符号或者常量放在操作符右邊的時候,計算機就讀取他們的“右值”,也就是其代表的真實值。簡單來說就是,左值相當于位址值,右值相當于資料值。右值指的是引用了一個存儲在某個記憶體位址裡的資料。

以上内容為本人學習摘錄,來源多為網上搜尋所得,如您認為侵犯您的版權,請留言告知,不勝感激。

繼續閱讀