Vector <bool> :: operator [] misbehavior?
Possible duplicate:
Why does vector <bool> :: reference not return a link to bool?
I used to think that with std::vector::operator[] we get copies of the deepest available element, but it seems that this is not always the case. At least with vector<bool> following test code gives a different result:
#include <iostream> #include <vector> using namespace std; template <typename T> void Test(const T& oldValue, const T& newValue, const char* message) { cout << message << '\n'; vector<T> v; v.push_back(oldValue); cout << " before: v[0] = " << v[0] << '\n'; // Should be a deep-copy (?) auto x = v[0]; x = newValue; cout << " after: v[0] = " << v[0] << '\n'; cout << "-------------------------------\n"; } int main() { Test<int>(10, 20, "Testing vector<int>"); Test<double>(3.14, 6.28, "Testing vector<double>"); Test<bool>(true, false, "Testing vector<bool>"); } Output (source code compiled with VC10 / VS2010 SP1):
Testing vector<int> before: v[0] = 10 after: v[0] = 10 ------------------------------- Testing vector<double> before: v[0] = 3.14 after: v[0] = 3.14 ------------------------------- Testing vector<bool> before: v[0] = 1 after: v[0] = 0 ------------------------------- I would expect that v[0] after assigning x = newValue would still be equal to its previous value, but that seems wrong. Why is this? Why is vector<bool> special?
vector<bool>::operator[] does not give a bool or a link to a bool . It simply returns a small proxy object that acts as a link. This is because there are no links to individual bits, and vector<bool> stores bool compressed way. Thus, using auto , you just created a copy of this reference object. The problem is that C ++ does not know that this object acts as a link. You have to force "decay to value" here by replacing auto with T
vector<bool> - disgusting abomination and feature. The committee specialized in packing bits, so it does not support the correct reference semantics, since you cannot refer to bits, this means that it has an inappropriate interface and does not really qualify as a standard container. The solution that most people use is simply never using vector<bool> .
operator[] returns T& for each T value, except for bool , where it gives a reference proxy. See this old Herb Sutter column on why using vector<bool> in generic code is a bad idea (and why it's not even a container). There is also a special item on this in the Effective STL from Scott Meyers and tons of questions on it here at SO.