Ранжированное основание для l oop для вектора логических значений - PullRequest
4 голосов
/ 16 января 2020

std::vector<bool> использует прокси-итераторы.

Таким образом, следующий код не скомпилируется (код взят из принятого ответа в связанном вопросе ):

vector<bool> v = {true, false, false, true};
for (auto& x : v)
    x = !x;

В соответствующем вопросе принятый ответ гласит, что чтобы изменить компоненты вектора на месте, мы должны использовать

for (auto&& x : v)
    x = !x;

Но если я просто сделаю:

for (auto x : v)
    x = !x;

Это даст идентичные результаты. Так что && не нужен?

Далее, почему следующие 2 кода не изменяют компоненты?

for (bool &&x : v)
    x = !x;

и

for (bool x : v)
    x = !x;

1 Ответ

5 голосов
/ 16 января 2020

TL; DR: прокси-объект знает, как читать и записывать отдельные биты, независимо от того, как вы их храните. Преобразование прокси-объекта в bool теряет эту информацию.


for (auto&& x : v)
    x = !x;

и

for (auto x : v)
    x = !x;

ведут себя одинаково, поскольку в каждом случае прокси-объект (std::vector<bool>::reference) полученный из разыменования std::vector<bool>::iterator сохраняется в x. Независимо от того, хранится ли прокси-объект по значению или по ссылке, его значение модификации прокси-бита одинаково.

In

for (bool &&x : v)
    x = !x;

и

for (bool x : v)
    x = !x;

прокси-объект неявно преобразуется в bool. Это неизбежно приводит к потере информации, необходимой (и, следовательно, возможности) для воздействия на сжатый бит.

Обратите внимание, что все они определяются реализацией. Ваша реализация также может предвидеть go оптимизацию пространства, и в этом случае поведение, которое вы видите, может быть другим. Только auto&& работает в каждом случае.

...