Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a const std::vector apply const to the contained objects?

Tags:

c++

I know that const std::vector<int> applies the const to the ints, too, (e.g. begin() const will return a const_iterator). I am curious as to the reason for this. In my mind it would make more sense to apply the const only to the vector (e.g. no resizing), and leave contained object's constness to them (e.g. std::vector<const int>).

Is there a good reason for this? If so, can someone please explain it to me? Or is it just an oversight from the original days of the STL that can't be corrected anymore because of backwards compatibility?

like image 263
Baruch Avatar asked Jan 26 '23 00:01

Baruch


1 Answers

Const-ness in C++ is a semantic concept that means "the observable state of this object cannot be changed using this name." In the case of a vector, its contents are considered part of its observable state, so if the vector is const then its elements necessarily are also const.

This also means you can give some other code a const reference to your vector and have some certainly that it's not going to change the vector on you (reference made explicit here for illustration):

std::vector<int> a = create_a_vector();
std::vector<int> const & b = a;
something_else(b);

Unless something_else() is deviously going to cast away the const qualifier, you can be sure that it won't be mutating the vector or its contents in any way.

If the type worked as you proposed, you would have to copy the vector:

std::vector<int> a = create_a_vector();
std::vector<const int> b = a;
something_else(b);

If the vector is huge, this would have quite a big impact on performance.


Addendum: The crux of the question seems to be "why are the contents of the vector part of the observable state?"

The best way I can explain this is to illustrate it through the following questions:

  • If you copy a vector, do the elements get copied?
  • If you compare two vectors for equality, are the elements compared, or just the properties of the vector (the size)?

If the answers to these questions are "yes" then the elements themselves are also part of the observable state. So, this establishes a kind of rule: whatever gets copied during copy-construction/assignment or compared during an equality test is part of the observable state of an object.

For vector, the answers are "yes." Therefore, the elements are considered part of the observable state of the vector, and they must be considered const if the vector itself is const.

Contrast this with std::unique_ptr. Only the pointer value itself is part of the observable state; the pointer value of a const std::unique_ptr<int> cannot be mutated, but the pointer target can. This makes sense, because:

  • (You can't copy a std::unique_ptr, so we can't consider this part of the test.)
  • If you compare two std::unique_ptrs for equality, only the pointer value is actually compared; the value of the target is not.

Therefore, for std::unique_ptr, the value of the target is not part of the observable state and the const-ness of the std::unique_ptr object is irrelevant with regards to whether the pointer target can be mutated.

like image 84
cdhowie Avatar answered May 13 '23 00:05

cdhowie