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向量
*(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向量
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_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
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 &
.
向量的类型应该是向量
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向量
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_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
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 &
.
向量的类型应该是向量
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.
总之,对于模板而不是指针,一致性是传递性的。如果你在模板中放入指针,你会得到这两个行为。