C++中auto的優點和使用注意


一、優點

(一)避免忘記初始化

寫C++時忘記初始化常常會導致難以發現的bug,而使用auto則可以避免這一風險,因為像auto x;這樣的語句編譯器是不會通過的——連初始化都沒有,編譯器沒辦法推導出x的類型。

(二)避坑

有時會忘記正在使用的數據結構包含的類型到底是什么,使得我們預期的類型和實際類型不一樣。舉個栗子,如果你對效率有很高的追求,那么下面這樣的代碼不能達到令你滿意的效果:

unordered_map<int, int> m ({ {1,1}, {2,2} });
do_sth (const pair<int, int>& p);//將m的元素作為實參

這段代碼本意是想通過傳引用傳參避免復制、提高效率,但其實這段代碼運行時還是將實參復制了一遍。因為unordered_map的元素為pair<const key, value>類型,所以編譯器要先對pair<const key, value>類型的值進行復制操作,產生一個pair<key, value>類型的臨時變量,再將p與這個臨時變量進行綁定。而如果把上述代碼中的函數簽名改為const auto& p,那么就可以直接進行綁定了。
為了驗證上面這段描述的正確性,我們用代碼驗證如下:

unordered_map<int, int> m ({ {1,1}, {2,2} });//unordered_map的元素為pair<const key, value>類型
//對auto_p取址會得到*m.begin()的地址
const auto& auto_p = *m.begin();
//若上面的描述正確,那么對p取址會得到臨時變量的地址,它與auto_p的取址結果不同
const pair<int, int>& p = *m.begin();
//將取址結果轉化為int儲存起來
int p_address = (int)&p, auto_p_address = (int)&auto_p;

if (p_address == auot_p_address)
    cout << "t";
else
    cout << "f";

輸出為f,說明上面的描述正確。
避坑的另一方法就是查看文檔源代碼

(三)使重構簡單

如果有一天需要把int x改為long long x,只需要更改值就可以了。

二、使用注意

(一)型別推導通常忽略引用

關於型別推導的內容看這篇。例如,用auto作為函數返回類型時,即使return arr[i],返回值也不是引用。

(二)隱形代理類

例如,vector<bool>::operator []返回的是vector<bool>::reference型別的對象(vector 中嵌套的一個類)。再例如,一些C++庫中的類采用了表達式模板。此時使用auto就會導致得到的類型和我們預期的不一樣。

解決方法是:1.查看文檔或源代碼來弄清楚是否有代理類的存在。2.使用static_cast 進行類型轉換以確保得到的類型是我們想要的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM