Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is dereferenced element in const vector of int pointers mutable?

I am not sure the true meaning of const vector<int *> so I compiled the code below to get an idea but am now more confused.

vector<int *> v;
int x = 1, y = 2;
v.push_back(&x);
v.push_back(&y);

const vector<int *> w = v;
w[0] = &y;   //failed. Element is a constant pointer?
*(w[0]) ++;  //failed. Element pointer references to constant value?

If I had stopped here, I would have assumed that const vector<int *> is a vector of const int * const, but then I tried the following which clearly contradicted that assumption.

*(w[0]) += 3; //passed. Value not constant?
*(w[0]) = 20; //passed. Why...

Now *(w[0]) for reason unknown to me obviously treats ++ and += and assignment differently. I convinced myself that const vector only declares a constant object of the vector class and that the above results might depend on the actual implementation of the operator overloading of vector class. But I can't wrap my head around this. Can anyone help explain, please?

If it is relevant, I used g++ 4.2 on a Mac.

like image 620
user8578429 Avatar asked Sep 08 '17 07:09

user8578429


3 Answers

Why is dereferenced element in const vector of int pointers mutable?

For const vector<int *>, the element would be const pointer to non-const, i.e. int * const, so you can modify the object pointed by the pointer, but not the pointer itself.

According to Operator Precedence, postfix increment operator has higher precedence than operator*, so *(w[0]) ++; is equivalent to

* ((w[0]) ++); 

The increment on the pointer is performed at first, then it fails. w[0] = &y; is also trying to modify the pointer, so it fails too.

On the other hand, (*w[0]) ++; (i.e. increment on the pointee) would be fine. And the following statements are fine too, because they're both modifying the objects pointed by the pointer, not the pointers.

*(w[0]) += 3; //passed. *(w[0]) = 20; //passed. 
like image 63
songyuanyao Avatar answered Oct 11 '22 13:10

songyuanyao


It's a matter of operator precedence.

When you do *(w[0]) ++ you attempt to modify the pointer.

When you do *(w[0]) += 3 you modify the data pointed to by the pointer.

like image 28
Some programmer dude Avatar answered Oct 11 '22 13:10

Some programmer dude


w is a const vector<int *>. The const qualifier is applied to the vector. Therefore, the corresponding const member function will be used for the operator[]:

const_reference operator[]( size_type pos ) const;

Since the vector is const-qualified and contains elements of type int * ( and not const int *), the type of the expression w[0] is int * const& (instead of const int *&). That is, it is a reference to a constant pointer to an int and not a reference to a pointer to a constant int: the constness is applied to the the pointer itself, not to the data being pointed.

By doing *(w[0]) += 3 you are not modifying the value of the pointer the vector returns (which is const), but the value this pointer is pointing to. Since this pointer is of type int * const (and not const int *), you can modify what it is pointing to, so it does work. However, doing w[0] = &y is performing an assignment on a constant pointer, so it does not compile.

like image 26
ネロク・ゴ Avatar answered Oct 11 '22 13:10

ネロク・ゴ