Почему неконстантный вектор & lt; bool & gt; элементы const?

Когда я перебираю vector<bool>Я считаю, что элементы, разыменованные через итератор, распознаются так, как если бы они были постоянными. Это почему? Измените контейнер или тип элемента, например list<bool> или же vector<short>и элементы не являются постоянными. Этот код показывает, о чем я говорю:

typedef bool T;
#define C vector
istringstream &operator>>(istringstream &iss, T &v)
{
cout << "non-const" << endl;
return iss;
}

istringstream &operator>>(istringstream &iss, const T &v)
{
cout << "const" << endl;
return iss;
}

istringstream &operator>>(istringstream &iss, C<T> &c)
{
for (C<T>::iterator it = c.begin(); it != c.end(); ++it)
{
iss >> *it;
}
return iss;
}

int main()
{
C<T> c(1);
istringstream iss("1");
iss >> c;
}

За vector<bool>эта программа выводит «const» на консоль. Измените typedef и постоянную манифеста в верхней части на что угодно, кроме этих двух комбинаций, и вы получите «non-const». Кроме того, если я заменю строку, iss >> *it, с T v; iss >> v; *it = v;работает как положено — все комбинации печатаются как «неконстантные».

Я вижу такое же поведение с GCC 4.1.2 C ++ 98 (через codepad.org) и VS2015 C ++ 14+ (?).

2

Решение

Несмотря на название, vector<bool> не содержит bools, и разыменование его итератора не дает вам bool&, Вместо этого он дает вам объект типа vector<bool>::reference, который пытается подражать поведению bool& столько, сколько может.

Там нет никакого способа, чтобы преобразовать vector<bool>::reference к bool&поэтому неконстантная перегрузка не работает. vector<bool>::reference однако может быть преобразован в boolкоторый может затем связать с const bool&,

6

Другие решения

Чтобы сохранить память, vector<bool> не фактический массив bool, Значение bool должно быть сохранено только немного, но наименьший возможный размер составляет 1 байт = 8 бит. Следовательно, не используя тривиальную реализацию, вы можете иметь в 8 раз более эффективное хранилище (насколько это касается памяти), чем то, что мог бы обеспечить простой массив bool.

Однако следствием является то, что элемент vector<bool> это не бул, а vector<bool>::reference что почти, но не совсем так же, как bool&, Большинство операций здесь, но некоторые нет (как |= например)

Тем не менее, вы можете преобразовать его в boolили инициализировать новый const bool возражать с этим … и делать все, что вы, что с этим новым объектом

5

std::vector<bool> это специализация std::vector который действует пространственно-эффективный динамический набор битов. Итераторы вернулись из begin() а также end() фактически указывают на объекты типа прокси-класса, представляющие логические значения.

Ссылки, возвращаемые при разыменовании итераторов, являются значениями типа класса, а не фактическими логическими значениями. Преобразуется в значение bool type, поэтому перегрузка, принимающая ссылку на const, допускается (значения могут связываться со ссылками на const).

2
По вопросам рекламы [email protected]