为什么在int指针的const向量中去引用元素是可变的?

时间:2021-01-04 21:16:39

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.

我不确定const vector 的真正含义,所以我编译了下面的代码来获得一个想法,但是现在我更加困惑了。

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.

如果我停在这里,我就会假设const向量 是const int * const的一个向量,但是我尝试了下面的方法,这显然与这个假设相矛盾。

*(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?

现在*(w[0])出于我所不知道的原因,显然对++和+=和赋值有不同的看法。我确信const向量只声明向量类的一个常量对象,并且上述结果可能取决于向量类的运算符重载的实际实现。但我不能就此打住。谁能解释一下吗?

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

如果相关的话,我在Mac电脑上使用了g++ 4.2。

4 个解决方案

#1


33  

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

为什么在int指针的const向量中去引用元素是可变的?

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.

对于const向量 ,元素将是指向非const的const指针,即int * const,因此可以修改指针指向的对象,但不能修改指针本身。

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

根据运算符的优先级,后缀递增运算符的优先级高于运算符*,则*(w[0]) ++;相当于

* ((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.

指针的增量首先执行,然后失败。w[0]= y;也尝试修改指针,所以它也失败了。

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]) ++;(即在点上增加)就可以了。下面的语句也很好,因为它们都是修改指针指向的对象,而不是指针。

*(w[0]) += 3; //passed.
*(w[0]) = 20; //passed.

#2


9  

It's a matter of operator precedence.

这是一个操作符优先的问题。

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

当您执行*(w[0]) +时,您尝试修改指针。

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

当您执行*(w[0]) += 3时,您将修改指针指向的数据。

#3


5  

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[]:

w是一个const向量 。将const限定符应用于向量。因此,运算符将使用相应的const成员函数[]:

const_reference operator[]( size_type pos ) const;

const_reference运算符[](size_type pos);

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.

由于向量是const限定的,并且包含int *类型的元素(而不是const int *),所以表达式w[0]的类型是int * const&(而不是const int *&)。也就是说,它是对常量指针的引用,而不是对常量int指针的引用:一致性应用于指针本身,而不是指向数据。

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.

通过执行*(w[0]) += 3,您并没有修改向量返回的指针的值(这是const),而是这个指针指向的值。由于该指针类型为int * const(而不是const int *),所以您可以修改它所指向的内容,这样它就可以工作了。然而,执行w[0] = &y是在一个常量指针上执行赋值,因此它不会编译。

#4


1  

const vector<T> lets you access its elements as T const & (i.e. const T &). In this case, T is int *, so this is int * const &, a const reference to a pointer that points to an int. The pointer is constant, but the int is not.

const vector 允许您以T const &(即const T &)的形式访问其元素。在本例中,T是int *,所以这是int * const &,这是一个指向指向int的指针的const引用,指针是常量,但int不是。

The type of the vector would have needed to be vector<int const *> (i.e. vector<const int*>) in which case the elements would be accessed via int const * const &.

向量的类型应该是向量 (即向量 ),在这种情况下,元素将通过int const * const &访问。

Bottom line, constness is transitive with templates but not with pointers. And if you put pointers in templates, you get a bit of both behaviors.

总之,对于模板而不是指针,一致性是传递性的。如果你在模板中放入指针,你会得到这两个行为。

#1


33  

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

为什么在int指针的const向量中去引用元素是可变的?

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.

对于const向量 ,元素将是指向非const的const指针,即int * const,因此可以修改指针指向的对象,但不能修改指针本身。

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

根据运算符的优先级,后缀递增运算符的优先级高于运算符*,则*(w[0]) ++;相当于

* ((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.

指针的增量首先执行,然后失败。w[0]= y;也尝试修改指针,所以它也失败了。

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]) ++;(即在点上增加)就可以了。下面的语句也很好,因为它们都是修改指针指向的对象,而不是指针。

*(w[0]) += 3; //passed.
*(w[0]) = 20; //passed.

#2


9  

It's a matter of operator precedence.

这是一个操作符优先的问题。

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

当您执行*(w[0]) +时,您尝试修改指针。

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

当您执行*(w[0]) += 3时,您将修改指针指向的数据。

#3


5  

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[]:

w是一个const向量 。将const限定符应用于向量。因此,运算符将使用相应的const成员函数[]:

const_reference operator[]( size_type pos ) const;

const_reference运算符[](size_type pos);

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.

由于向量是const限定的,并且包含int *类型的元素(而不是const int *),所以表达式w[0]的类型是int * const&(而不是const int *&)。也就是说,它是对常量指针的引用,而不是对常量int指针的引用:一致性应用于指针本身,而不是指向数据。

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.

通过执行*(w[0]) += 3,您并没有修改向量返回的指针的值(这是const),而是这个指针指向的值。由于该指针类型为int * const(而不是const int *),所以您可以修改它所指向的内容,这样它就可以工作了。然而,执行w[0] = &y是在一个常量指针上执行赋值,因此它不会编译。

#4


1  

const vector<T> lets you access its elements as T const & (i.e. const T &). In this case, T is int *, so this is int * const &, a const reference to a pointer that points to an int. The pointer is constant, but the int is not.

const vector 允许您以T const &(即const T &)的形式访问其元素。在本例中,T是int *,所以这是int * const &,这是一个指向指向int的指针的const引用,指针是常量,但int不是。

The type of the vector would have needed to be vector<int const *> (i.e. vector<const int*>) in which case the elements would be accessed via int const * const &.

向量的类型应该是向量 (即向量 ),在这种情况下,元素将通过int const * const &访问。

Bottom line, constness is transitive with templates but not with pointers. And if you put pointers in templates, you get a bit of both behaviors.

总之,对于模板而不是指针,一致性是传递性的。如果你在模板中放入指针,你会得到这两个行为。