Effective Modern C++筆記(1)
阿新 • • 發佈:2020-09-03
Effective Modern C++
型別推導
模板推導的一般形式
template <class T>
void f(ParamType param); //函式宣告
f(expr); //函式呼叫
ParamType可以在T的基礎上加上const
,reference
等限制,比如const T&
函式引數型別是指標或引用(非通用引用universal reference)
template <class T> void f(T& param); //param是引用型別 int x = 42; const int cx = x; const int& crx = x; f(x); //T的型別是int,param的型別是int& f(cx); //T的型別是const int,param的型別是const int& f(crx); //T的型別是const int,param的型別是const int&
-
const屬性會被保留,但是crx的引用型別在型別推導時會被忽略。
-
如果把T&修改成const T&,那麼三種呼叫的T型別都是int,param的型別都是const int&
-
如果把引用T&改成T*,結果是類似的。
函式引數型別是通用引用
template <class T> void f(T&& param); //param是引用型別 int x = 42; const int cx = x; const int& crx = x; f(x); //T的型別是int&,param的型別是int& f(cx); //T的型別是const int&,param的型別是const int& f(crx); //T的型別是const int&,param的型別是const int& f(42); //T的型別是int,param的型別是int&&
當expr是左值(可取址)時,那麼T和paramType都被推導成左值引用。首先,這是唯一一種paramType被推導成引用的情況;其次,即便paramType宣告為右值引用,推導結果還是左值引用。
函式引數型別不是指標或者引用
template <class T>
void f(T param); //param通過值傳遞
int x = 42;
const int cx = x;
const int& crx = x;
//以下的T型別和paramType都是int
f(x);
f(cx);
f(crx);
值傳遞進來是呼叫的函式引數副本,副本完全獨立於原引數,const
reference
,volatile
屬性在型別推導時均被忽略。
const char* const ptr = "Fun with pointers";
f(ptr); //param的型別是 const char*
對於常量指標常量,情況有一點特殊。ptr可以指向別處,但是ptr指向的字串是不可修改的。
陣列型別/函式名
const char name[] = "Scott Meyers"; //const char[12]
const char* ptrToName = name; //陣列到指標是某種“退化”,指向首元素的地址
函式宣告時,引數int param*和int param[]效果時一樣的。
當值傳遞時,型別推導結果是const char*
當引用傳參時,型別推導結果是const char[12]
(the synyax looks toxic,這語法有毒)
template<class T, std::size_t N>
constexpr std::size_t arraySize(T& [N])noexcept{ //constexpr在編譯期可以確定值,noexcept不會丟擲異常
return N;
}
需要記住的是:
- 型別推導過程中,引數的引用屬性會被忽略
- 通用引用引數,左值引數情況特殊,始終推導成左值
- 值傳遞時,const/volatile等屬性會被忽略
- 陣列或者函式名會被推導成指標,除非宣告為引用型別
待續~
reference
Effective Modern C++ by Scott Mey‐ ers (O’Reilly). Copyright 2015 Scott Meyers, 978-1-491-90399-5.