Когда я перебираю 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+ (?).
Несмотря на название, vector<bool>
не содержит bool
s, и разыменование его итератора не дает вам bool&
, Вместо этого он дает вам объект типа vector<bool>::reference
, который пытается подражать поведению bool&
столько, сколько может.
Там нет никакого способа, чтобы преобразовать vector<bool>::reference
к bool&
поэтому неконстантная перегрузка не работает. vector<bool>::reference
однако может быть преобразован в bool
который может затем связать с const bool&
,
Чтобы сохранить память, vector<bool>
не фактический массив bool
, Значение bool должно быть сохранено только немного, но наименьший возможный размер составляет 1 байт = 8 бит. Следовательно, не используя тривиальную реализацию, вы можете иметь в 8 раз более эффективное хранилище (насколько это касается памяти), чем то, что мог бы обеспечить простой массив bool.
Однако следствием является то, что элемент vector<bool>
это не бул, а vector<bool>::reference
что почти, но не совсем так же, как bool&
, Большинство операций здесь, но некоторые нет (как |=
например)
Тем не менее, вы можете преобразовать его в bool
или инициализировать новый const bool
возражать с этим … и делать все, что вы, что с этим новым объектом
std::vector<bool>
это специализация std::vector
который действует пространственно-эффективный динамический набор битов. Итераторы вернулись из begin()
а также end()
фактически указывают на объекты типа прокси-класса, представляющие логические значения.
Ссылки, возвращаемые при разыменовании итераторов, являются значениями типа класса, а не фактическими логическими значениями. Преобразуется в значение bool
type, поэтому перегрузка, принимающая ссылку на const, допускается (значения могут связываться со ссылками на const).