說說 auto

pezy發表於2019-05-11

自動推導基礎

auto 關鍵字的推導過程完全處於 compile-time,所以並不會影響程式效能。應該放心大膽的使用。

cppauto i = 1; // i will become int
auto l = 1LL; // l will become long long
auto d = 1.0; // d will become double
auto f = 1.0f; // f will become float

std::vector<int> ivec{1, 2, 3, 4, 5};
for (auto i : ivec) std::cout << i << " "; // 1 2 3 4 5

這樣使用 auto 可能會要求你記住一些字面量的型別標識

  • 前置
    標識 含義 型別
    u Unicode 16 character char16_t
    U Unicode 32 character char32_t
    L wide character wchar_t
    u8 utf-8(string literals only) char

可能經常用 VS 和 Windows API 的人比較熟悉 L,用來標識寬字元。(不得不說,這一點,微軟還是挺超前的)

  • 後置
    字面量 標識 型別
    整型 u / U unsigned
    整型 l / L long
    整型 ll / LL long long
    浮點 f / F float
    浮點 l / L long double

這些與 C 語言一脈相承,應該比較熟悉了。


特殊情況

cppauto str = "hello";

請問,str 是什麼型別?最近才發現,很多初學者竟然想當然的認為strstd::string.(尤其是沒有 C 語言基礎的)

實際上,str 此時是 const char *.

所以當你對 str 進行 range for 的時候,就會傻眼。

cppfor (auto c : str) { // error! str 沒有 begin() 和 end()
//...
}

上述情況應該如何避免?

cppauto& str = "hello";

請問,str是什麼型別?

const char[6]. 這是一個陣列了,那麼 range for 當然沒問題了。

還有別的方法嗎?

當然,右值引用不是吃閒飯的:

cppauto&& str = "hello";

range for 照樣沒問題。請問 str 此刻是什麼型別?

const char(&)[6].

這都是非常基礎的內容,你都清楚嗎?

另外補充一個:

cppauto il = {1, 2, 3, 4, 5, 6};

不要覺得 il 會是 std::array 或 普通陣列,甚至是 std::vector. 它的型別應該是: std::initializer_list


什麼時候該用 auto

  • 一種說法是:能用 auto 的地方都該用。(尤其是受到 python 等動態語言影響的人)。
  • 另一種說法:auto 會讓程式碼變得不直觀,在一個強型別的語言中,會搞得人莫名其妙。

經過一段時間的瘋狂實踐。我覺得上述兩種觀點都有失偏頗。

其實,開始我是支援第一種觀點的,於是開始大量使用 auto, 直到有一天 review 自己的程式碼時。竟然發現很多變數完全看不出是什麼型別。如:

cppauto foo = bla(); // 請問 foo 你能看出型別來嗎?

這就傻眼了。違反了最基本的程式設計原則——“清晰易懂,方便擴充套件”,看都看迷糊了,擴充套件毛啊。

但有些情況,其實極大程度上的簡化了程式,使之簡潔明瞭:

cppauto foo = std::make_shared<Foo>(); // 一看就知道型別

for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter) {} // 一看就知道型別

上述兩種情況下,把 auto 擴充套件開來,會顯得重複、冗長。

這兩個例子,應該能夠說明使用 auto 的那條 “金線” 在哪了。我們的目的不是為了用而用,而是儘可能的讓自己的程式,易於維護,保持新鮮

故,不要濫用,不要避諱。

相關文章