1. 程式人生 > 實用技巧 >Effective Modern C++筆記(1)

Effective Modern C++筆記(1)

Effective Modern C++

型別推導

模板推導的一般形式
template <class T>
void f(ParamType param);  //函式宣告
f(expr);  //函式呼叫

ParamType可以在T的基礎上加上constreference等限制,比如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&
  1. const屬性會被保留,但是crx的引用型別在型別推導時會被忽略。

  2. 如果把T&修改成const T&,那麼三種呼叫的T型別都是int,param的型別都是const int&

  3. 如果把引用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;
}

需要記住的是:

  1. 型別推導過程中,引數的引用屬性會被忽略
  2. 通用引用引數,左值引數情況特殊,始終推導成左值
  3. 值傳遞時,const/volatile等屬性會被忽略
  4. 陣列或者函式名會被推導成指標,除非宣告為引用型別

待續~

reference

Effective Modern C++ by Scott Mey‐ ers (O’Reilly). Copyright 2015 Scott Meyers, 978-1-491-90399-5.