Подтвердить что ты не робот

Диапазоны для циклов и 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)
4b9b3361

Ответ 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&.