自動和代理物件

有時 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 更有意義。

代理物件可能導致問題的另一種情況是表示式模板 。在這種情況下,為了提高效率,模板有時不會設計為超出當前的完整表示式,並且在下一個上使用代理物件會導致未定義的行為。