4

I have this code:

#include <iostream> #include <vector> using namespace std; int main(){ vector <bool> v; cin >> v[0]; return 0; } 

Why can't I do that? The compiler won't compile that, but I have other variable types in the vector, it will work just fine. What's the problem with this?

0

3 Answers 3

11

It's because std::vector<bool> is a specialization and doesn't act like a vector at all. This is widely recognized to be a major flaw in the Standard.

In order to save memory, vector<bool> stores each element as a single bit. But bits aren't individually addressable, so operator[] can't return a bool& reference connected to a bit. Instead it returns vector<bool>::reference... and cin doesn't provide function overloads to deal with this.

(juanchopanza correctly points out that your vector didn't have an element zero. But even if it did via resize or other mechanism, the fact that operator[] doesn't return a reference still gets in the way.)

Sign up to request clarification or add additional context in comments.

9 Comments

Thank you, this is more than enough.
Actually, I don't think the strangeness of std::vector<bool> is an issue in this case.
@juanchopanza Why not? Even if I push some elements in the vector, so v[0] exists, I still get that compilation error.
@MyUserIsThis what compiler? I don't get that problem on GCC 4.7.2: see this demo.
I think assignment via operator[] is OK, but taking the address of whatever it returns would not work.
|
3

At the time you call v[0], the vector has zero size, so you are accessing out of bounds. This is undefined behaviour.

Furthermore, std::vector<bool> is a specialization which has strange behaviour due to the fact that it does not hold individual bool elements. Its operator[] returns a kind of proxy object, the call to that operator may not do what you expect. It should be used with care, or not used at all.

You can solve the problem by reading a value into a local variable and then pushing it into the back of the vector, as in this working example (similar live demo here):

#include <vector> #include <iostream> int main() { std::vector<bool> v; std::cout << std::boolalpha; v.push_back(true); std::cout << v[0] << std::endl; bool b; cin >> b; v[0] = b; std::cout << v[0] << std::endl; } 

2 Comments

You are correct about the out-of-bounds access. However, I think that's tangential to the question. Imagine that v.resize(1) was called.
@BenVoigt that makes my head hurt! I have successfully avoided std::vector<bool> for so many years now that I am not sure anymore where it breaks and where not.
1

This should work:

#include <iomanip> ... bool a; cin >> boolalpha >> a; v.push_back(a); 

(In addition to the problem mentioned by Ben Voigt, your current code isn't safe with types other than bool because your vector is empty when you're accessing v[0].)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.