Диапазоны для циклов и std::vector <bool>
Почему этот код работает
std::vector<int> intVector(10);
for(auto& i : intVector)
std::cout << i;
И это не так?
std::vector<bool> boolVector(10);
for(auto& i : boolVector)
std::cout << i;
В последнем случае я получаю сообщение об ошибке
ошибка: недействительная инициализация не-const ссылки типа 'std:: _ Bit_reference & из rvalue типа 'std:: _ Bit_iterator:: reference {aka std:: _ Bit_reference}
for(auto& i : boolVector)
Ответы
Ответ 1
Потому что std::vector<bool>
не является контейнером!
std::vector<T>
Итераторы обычно разыгрывают a T&
, которые вы можете привязать к своему auto&
.
std::vector<bool>
, однако, упаковывает его bool
вместе внутри целых чисел, поэтому для доступа к ним требуется прокси-сервер для маскировки бит. Таким образом, его итераторы возвращают a Proxy
.
И так как возвращенный Proxy
является prvalue (временным), он не может связываться с ссылкой на lvalue, например auto&
.
Решение: используйте auto&&
, который будет правильно скомпонован в ссылку lvalue, если он указан, или привяжите и сохраните временную жизнь, если она предоставила прокси.
Ответ 2
std::vector<bool>
не подчиняется стандартным правилам контейнера.
В частности, его operator[]
не возвращает bool&
.
Цикл недопустимого кода
#include <vector>
#include <iostream>
int main() {
std::vector<bool> boolVector(10);
for (auto& i: boolVector)
std::cout << i;
}
можно переписать любым из трех способов для итерации значений:
-
(только для чтения)
for (auto i: boolVector)
std::cout << i;
-
(только для чтения, возможно, неэффективно)
for (auto const& i: boolVector)
std::cout << i;
-
(чтение/запись)
for (auto&& i: boolVector)
std::cout << i;
Выбор между первым и последним сводится к тому, нужно ли изменять значения в векторе или просто читать их.
Ответ 3
vector<bool>
(обычно) специально предназначен для хранения каждого bool
в одном бите, что уменьшает затраты на хранение с одного байта на одно значение на один байт за восемь значений. Никакой процессор, который я знаю, не может быть адресован бит, поэтому невозможно сохранить ссылку на значения в vector<bool>
. Для значения итерации i
вам нужно использовать обычный auto
, а не auto&
.