慎用auto關鍵詞


C++11 標准推出了一個新的關鍵詞auto,這個關鍵詞可以通過表達式自動推斷返回值的類型,這也是新標准中被各編譯器廠商支持最為廣泛的特性之一。利用這個關鍵詞可以有效減少代碼的長度,特別是在使用模板元編程的時候。

舉個簡單的例子:

vector<map<int, string>> stringMapArray;

    

// 不使用auto版本

vector<map<int, string>>::iterator iter1 = stringMapArray.begin();

    

// 使用auto版本

auto iter2 = stringMapArray.begin();

看到這樣簡短的式子,我再也不能忍受第一個包含大量冗余信息的式子了。所以,最近寫的C++里到處都是auto,恨不得在lambda的參數列表里也用(可惜不行)。

但是物極必反,auto的濫用卻使一個非常隱蔽的問題悄然出現。最近寫一個正則引擎的時候,發現運行效率總是低於預期,剛開始認為是動態內存分配的問題,通過替換成內存池后發現雖然效率有所提高,但是仍然達不到要求。於是想到了性能工具,一次檢查下來發現如下語句竟然占用了70%的時間:

// 函數聲明

set<int>& getSet();

 

void foo()

{

    // 占用70%的時間

    auto s = getSet();

    

    ...

}

檢查發現原來auto把函數的返回值推斷成了set<int>而不是set<int>&這使得在賦值的時候發生了集合的復制,而這個集合包含了6萬多個數據,這使得本應幾乎不花時間的引用操作變成了耗時巨大的復制操作。

查了下C++標准 ISO/IEC 14882 Third edition P157,auto關鍵詞的類型推斷其實和模板的類型推斷一致

§ 7.1.6.4 auto specifier

If the list of declarators contains more than one declarator, the type of each declared variable is determined as described above. If the type deduced for the template parameter U is not the same in each deduction, the program is ill-formed.

const auto &i = expr;

The type of i is the deduced type of the parameter u in the call f(expr) of the following invented function template:

template <class U> void f(const U& u);

所以之前的表達式相當於:

set<int>& getSet();

 

template <typename T>

void foo(T t);

 

void bar()

{

    // 這里的參數T推斷成了set<int>,而不是set<int>&

    foo(getSet());

}

如果我們想要獲得引用類型,就要顯式地寫:

auto& refValue = getSet();

經過修改之后,這條語句的執行時間已經下降到忽略不計了。

這個教訓告訴我們,使用auto的時候雖然省事,但還是需要仔細考慮一下得到的類型到底是什么。


免責聲明!

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



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