const vector implies const elements?

C++Constants

C++ Problem Overview


Does const vector<A> mean that its elements are constas well?

In the code below,

v[0].set (1234); in void g ( const vector<A> & v ) produces the compiler error

> const.cpp:28:3: error: member function 'set' not viable: 'this' > argument has > type 'const value_type' (aka 'const A'), but function is not marked const

Why?

But (*v[0]).set(1234); in void h ( const vector<A *> & v ) is OK for the compiler.

What's the difference between the versions?

// ...........................................................
class A {
private:
  int a;
public:
  A (int a_) : a (a_) { }
  int get () const { return a; }
  void set (int a_) { a = a_; }
};

// ...........................................................
void g ( const vector<A> & v ) {
  cout << v[0].get();
  v[0].set (1234); 
} // ()

// ...........................................................
void h ( const vector<A *> & v ) {
  cout << (*v[0]).get();
  (*v[0]).set(1234);
} // ()

C++ Solutions


Solution 1 - C++

Yes, a const vector provides access to its elements as if they were const, that is, it only gives you const references. In your second function, it's not the objects of type A that are const, but pointers to them. A pointer being const does not mean that the object the pointer is pointing to is const. To declare a pointer-to-const, use the type A const *.

Solution 2 - C++

The first version

v[0].set (1234); 

does not compile because it tries to change the vector's first element returned to it by reference. The compiler thinks it's a change because set(int) is not marked const.

The second version, on the other hand, only reads from the vector

(*v[0]).set(1234);

and calls set on the result of the dereference of a constant reference to a pointer that it gets back.

When you call v[0] on a const vector, you get back a const reference to A. When element type is a pointer, calling set on it is OK. You could change the second example to

v[0]->set(1234);

and get the same result as before. This is because you get a reference to a pointer that is constant, but the item pointed to by that pointer is not constant.

Solution 3 - C++

So a const object can only call const methods. That is:

class V {
  public:
    void foo() { ... }        // Can't be called
    void bar() const  { ... } // Can be called
};

So let's look at a vector's operator[]:

reference       operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;

So when the vector object is const, it will return a const_reference.

About: (*v[0]).set(1234);

Let's break this down:

A * const & ptr = v[0];
A & val = *ptr;
val.set(1234);

Note that you have a constant pointer to variable data. So you can't change what is pointed at, but you can change the value that the pointer points at.

Solution 4 - C++

Yes, because std::vector is a value-type rather than a reference type.

To simplify things: An std::vector considers the values in its buffer as part of itself, so that changing them means changing the vector. This may be confusing if we only think of a vector as holding a pointer to an allocated buffer and the size: We don't change these two fields when we change elements in the buffer.

It's the opposite than for pointers, which are reference-types; if you change the pointed-to value you haven't changed the pointer itself.

The fact that std::vector is a value-type is a design choice - it's not something inherent in the C++ language. Thus, for example, the std::span class is also basically a pair of a pointer and a size, but an std::span can be const while you can still change the pointed-to elements. (There are other differences between spans and vectors.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncibercitizen1View Question on Stackoverflow
Solution 1 - C++lisyarusView Answer on Stackoverflow
Solution 2 - C++Sergey KalinichenkoView Answer on Stackoverflow
Solution 3 - C++Bill LynchView Answer on Stackoverflow
Solution 4 - C++einpoklumView Answer on Stackoverflow