自動和代理物件
有時 auto
的行為可能與程式設計師的預期不同。它型別推斷表示式,即使型別推導不是正確的事情。
例如,在程式碼中使用代理物件時:
std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);
這裡 flag
不是 bool
,而是 std::vector<bool>::reference
,因為對於 bool
模板 vector
的特化,operator []
返回一個代理物件,其中定義了轉換運算子 operator bool
。
當 flags.push_back(true)
修改容器時,這個偽引用可能最終懸空,指的是一個不再存在的元素。
它還使下一種情況成為可能:
void foo(bool b);
std::vector<bool> getFlags();
auto flag = getFlags()[5];
foo(flag);
vector
立即被丟棄,因此 flag
是對已被丟棄的元素的偽引用。對 foo
的呼叫會呼叫未定義的行為。
在這種情況下,你可以使用 auto
宣告一個變數,並通過強制轉換為你想要推斷的型別來初始化它:
auto flag = static_cast<bool>(getFlags()[5]);
但在那時,簡單地用 bool
取代 auto
更有意義。
代理物件可能導致問題的另一種情況是表示式模板 。在這種情況下,為了提高效率,模板有時不會設計為超出當前的完整表示式,並且在下一個上使用代理物件會導致未定義的行為。