關鍵字: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;
}
關鍵字: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;
}
};
左值和右值
左值是代表一個記憶體位址值,并且通過這個記憶體位址,就可以對記憶體進行讀并且寫(主要是能寫)操作;這也就是為什麼左值可以被指派的原因了。相對應的還有右值:當一個符号或者常量放在操作符右邊的時候,計算機就讀取他們的“右值”,也就是其代表的真實值。簡單來說就是,左值相當于位址值,右值相當于資料值。右值指的是引用了一個存儲在某個記憶體位址裡的資料。
以上内容為本人學習摘錄,來源多為網上搜尋所得,如您認為侵犯您的版權,請留言告知,不勝感激。