Effective Modern C++ 系列之 條款2: auto
Effective Modern C++ 系列之 條款2: auto 型別推導
在理解模板型別推導規則後,那麼auto型別推導不是什麼問題了,除了一個奇妙的例外情況以外,auto型別推導就是模板型別推導.
template<typename T>
void f(ParamType param);
而一次呼叫形如:
f(expr);
在f呼叫中,編譯會根據expr來推導T和ParamType的型別.
當變數採用auto來宣告時, auto就扮演了模板中T的角色, 而變數的型別修辭詞則扮演的是ParamType的角色.
例如:
auto x = 27; (1) x的修飾詞就是auto自身 .
const auto cx = x; (2) cx的修飾詞 const auto .
const auto& rx = x; (3) rx的修飾詞 const auto& .
在C++中auto型別推導和模板型別推導是一模一樣的(除了在一個例外情況下),可以利用模板型別推導規則模擬auto型別推導過程如下:
template<typename T> //模擬auto型別推導過程.
void func_for_x(T param);
func_fox_x(27); // 推導得出param的型別就是X的型別.
template<typename T>
void func_for_cx(const T param);
func_for_cx(x) // 推導得出param的型別就是cX的型別.
template<typename T>
void func_for_rx(const T& param);
func_for_rx(rx); //推導得出的param的型別就是rx的型別.
1. auto型別推導與模板型別推導一模一樣的規則.
採用auto進行變數宣告中,型別修飾詞取代ParamType,所以也存在三種情況:
1.1 型別修飾詞是指標或引用,但不是萬能引用.
auto x = 27 ;
const auto cx = x ;
const auto& rx = x ;
1.2 型別修飾詞是萬能引用.
auto&& uref1 = x; // x的型別是int, 且是左值,所以uref1的型別是int&。
auto&& uref2 = cx; // cx的型別是const int, 且是左值. 所以uref2的型別是const int&.
auto&& uref3 = 27; // 27的型別是int, 且是右值. 所以uref3的型別是int&&.
1.3 型別修飾詞既非指標也非引用.
在條款1中,陣列和函式名字如何在非引用修飾詞的前提下退化成指標,也同樣適合auto型別推導
const char name[] = "J. P. Briggs"; //name的型別是const char[13].
auto arr1 = name; // arr1的型別是const char*.
auto& arr2 = name; // arr2的型別const char(&)[13].
void someFunc(int, double); //someFunc是個函式,型別是void(int, double).
auto func1 = someFunc; //func1的型別是void(*)(int, double).
auto& func2 = someFunc; //func2的型別是void(&)(int, double).
2. auto型別推導與模板型別推導不同存在差異的情況.
auto宣告變數的初始化表示式使用{}時,推導所得的型別屬於std::initializer_list
auto x = {1,2,3,4,3.0} //錯誤,推導不出std::initializer_list<T>中T.
模板傳入一個{}的初始化表示式,型別推導就會失敗
auto x = {1,2,3} //x的型別是std::initializer_list<int>
template<typename T>
void f(T param)
f({1,2,3,4}); // 無法推導T的型別.
注意: auto 和 模板型別推導真正的唯一區別在於,auto會假定用大括號括起來的初始化表示式代表一個std::initializer_list,但模板型別推導卻不會.
在函式返回值或者lambda式的形象中使用auto,意思是使用模板型別推導而非auto型別推導.
auto createInitList {
return {1,2,3,4}; //錯誤,無法為{1,2,3}完成型別推導.
}
std::vector<int> v;
...
auto resetv = [&v](const auto& newValue) { v = newValue }; //c++14
...
restv({1,2,3}); //錯誤!無法為{1,2,3}完成型別推導.
4. 總結
- 在一般情況下,auto型別推導和模板型別推導是一模一樣的,但是auto型別推導會假定用大括號括起來的初始化表示式代表一個std::initializer_list,但是模板型別推導卻不會.
- 在函式返回值或lambda式的形參中使用auto,意思是使用模板型別推導而非auto型別推導.
5. 驗證程式碼
#include <boost/type_index.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
using boost::typeindex::type_id_with_cvr;
int main(int argc, char** argv) {
auto&& x = 12;
std::cout << "param =" << type_id_with_cvr<decltype(x)>().pretty_name() << std::endl;
return 0;
}
本文學習《 Effective Modern C++ 》一書整理的學習筆記
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2157/viewspace-2825370/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 學懂現代C++——《Effective Modern C++》之型別推導和autoC++型別
- 【Effective Modern C++】索引C++索引
- 學懂現代C++——《Effective Modern C++》之轉向現代C++C++
- Effective C++ 條款08_不止於此C++
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- [讀書筆記][effective C++]條款30-inline的原理筆記C++inline
- effective C++ : CHAPTER 8C++APT
- Effective C++筆記C++筆記
- effective C++筆記1C++筆記
- 《Effective C++》讀書筆記C++筆記
- [譯]Effective Kotlin系列之使用Sequence來優化集合的操作(四)Kotlin優化
- Effective C++ 筆記(3)資源管理C++筆記
- Effective C++ 4.設計與宣告C++
- C++ 陣列的 auto 和 decltypeC++陣列
- [譯]Effective Kotlin系列之探索高階函式中inline修飾符(三)Kotlin函式inline
- <<Modern CMake>> 翻譯 2. CMake 基礎
- 條款01: 視C++為一個語言聯邦C++
- 《Effective C++》閱讀總結(三):資源管理C++
- C++ auto 型別推斷注意的地方C++型別
- 《Effective C++》第三版-1. 讓自己習慣C++(Accustoming Yourself to C++)C++
- JSON for Modern C++ 庫的介紹與使用示例程式碼JSONC++
- [譯]Effective Kotlin系列之考慮使用原始型別的陣列優化效能(五)Kotlin型別陣列優化
- (譯)Effective Kotlin系列之考慮使用靜態工廠方法替代構造器(一)Kotlin
- 三個白帽-條條大路通羅馬系列2-Writeup
- 條款05: 瞭解c++默默編寫並呼叫哪些函式C++函式
- 《Effective C++》第三版-5. 實現(Implementations)C++
- 讀完Java名著《Effective Java》: 我整理了這50條技巧Java
- Modern Pascal is Still in the Race (Modern Pascal 仍在競賽中)
- 深入解析C++的auto自動型別推導C++型別
- 《Effective C++》第三版-2. 構造析構賦值運算(Constructors,Destructors,and Assignment Operators)C++賦值Struct
- webpack系列之五module生成2Web
- MySQL5.7之auto_increment回溯MySqlREM
- 《Effective C++》閱讀總結(四): 設計、宣告與實現C++
- (譯)Effective Kotlin系列之遇到多個構造器引數要考慮使用構建器(二)Kotlin
- webpack系列之四loader詳解2Web
- 《Effective C++》第三版-3. 資源管理(Resource Management)C++
- Modern PHP(一)特性PHP
- Modern CMake 簡介