I know that const std::vector<int>
applies the const
to the int
s, 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?
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 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:
std::unique_ptr
, so we can't consider this part of the test.)std::unique_ptr
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With