Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 35
Скотт Мейерс
С учетом этой информации посмотрим еще раз на следующую часть исходного кода:
bool highPriority = features(w)[5]; // Явное объявление типа
// highPriority
Здесь features
возвращает объект std::vector<bool>
, для которого вызывается operator[]
. Этот оператор возвращает объект типа std::vector<bool>::referenc
e, который затем неявно преобразуется в значение типа bool,
необходимое для инициализации highPriority
. Таким образом, highPriority
в конечном итоге получает значение пятого бита из std::vector<bool>
, возвращенного функцией features
, так, как и предполагалось.
Но что же произойдет, если переменная highPriority
будет объявлена как auto
?
auto highPriority = features(w)[5]; // Вывод типа highPriority
Функция features
, как и ранее, возвращает объект типа std::vector<bool>
, и, как и ранее, выполняется его operator[]
. Оператор возвращает объект типа std::vector<bool>::reference
, но дальше привычный ход событий изменяется, так как auto
приводит к выводу типа переменной highPriority
. Теперь переменная highPriority
не получает значение пятого бита std::vector<bool>
, возвращенного вызовом features
.
Полученное ею значение зависит от того, как реализован тип std::vector<bool>::reference
. Одна из реализаций таких объектов состоит в том, чтобы содержать указатель на машинное слово с интересующим нас битом и смещение этого бита в слове. Рассмотрим, что это означает для инициализации highPriority
, в предположении, что имеет место именно такая реализация std::vector<bool>::reference
.
Вызов features
возвращает временный объект std::vector<bool>
. Этот объект не имеет имени, но для упрощения нашего рассмотрения я буду называть его temp
. Для temp
вызывается operator[]
, в результате чего возвращается объект std::vector<bool>::reference
, содержащий указатель на слово в структуре данных, хранящей интересующий нас бит (эта структура находится под управлением temp
), плюс смещение в слове, соответствующее пятому биту. Переменная highPriority
представляет собой копию этого объекта std::vector<bool>::reference
, так что highPriority
тоже содержит указатель на слово в temp
плюс смещение, соответствующее пятому биту. В конце инструкции объект temp
уничтожается, так как это объект временный. В результате переменная highPriority
содержит висячий указатель, что и дает неопределенное поведение при вызове processWidget
: