web-dev-qa-db-ja.com

intポインタのconstベクトルの逆参照された要素が変更可能であるのはなぜですか?

_const vector<int *>_の本当の意味がわからないので、以下のコードをコンパイルしてアイデアを得ましたが、今ではもっと混乱しています。

_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?
_

ここで停止した場合、_const vector<int *>_は_const int * const_のベクトルであると想定していましたが、その想定と明らかに矛盾する次のことを試みました。

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

*(w[0])は、理由がわからないため、明らかに_++_と_+=_および割り当てを異なる方法で処理します。 _const vector_はvectorクラスの定数オブジェクトのみを宣言し、上記の結果はvectorクラスの演算子オーバーロードの実際の実装に依存する可能性があることを確信しました。しかし、私はこれに頭を包むことはできません。誰かが説明を手伝ってもらえますか?

関連する場合は、Macでg ++ 4.2を使用しました。

29
user8578429

Intポインタのconstベクトルの逆参照された要素が変更可能であるのはなぜですか?

_const vector<int *>_の場合、要素は非constへのconstポインター、つまり_int * const_になるため、ポインターが指すオブジェクトを変更できますが、ポインターは変更できません。自体。

Operator Precedence によると、接尾辞インクリメント演算子は_operator*_よりも優先順位が高いため、*(w[0]) ++;はと同等です。

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

ポインタのインクリメントは最初に実行され、その後失敗します。 _w[0] = &y;_もポインタを変更しようとしているため、失敗します。

一方、_(*w[0]) ++;_(つまり、ポインティの増分)は問題ありません。また、次のステートメントも問題ありません。どちらも、ポインターではなく、ポインターが指すオブジェクトを変更しているためです。

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

演算子の優先順位 の問題です。

*(w[0]) ++を実行すると、ポインタを変更しようとします。

*(w[0]) += 3を実行すると、ポインターが指すデータが変更されます。

wは_const vector<int *>_です。 const修飾子​​がベクトルに適用されます。したがって、対応するconstメンバー関数が_operator[]_に使用されます。

const_reference operator[]( size_type pos ) const;

ベクトルはconst修飾されており、タイプ_int *_(_const int *_ではない)の要素が含まれているため、式_w[0]_のタイプは_int * const&_(代わりに)です。 _const int *&_)の。つまり、これはintへの定数ポインタへの参照であり、定数intへのポインタへの参照ではありません。 constnessは、ポイントされているデータではなく、ポインタ自体に適用されます。

*(w[0]) += 3を実行することにより、ベクトルが返すポインターの値const)を変更するのではなく、このポインターが指す値)を変更します。 to。このポインターのタイプは_int * const_(_const int *_ではない)であるため、ポインターが指しているものを変更して、機能するようにすることができます。ただし、_w[0] = &y_を実行すると、定数ポインターで割り当てが実行されるため、コンパイルされません。

6
El Profesor

const vector<T>を使用すると、その要素にT const &つまりconst T &)としてアクセスできます。この場合、Tint *であるため、これはint * const &であり、intを指すポインターへのconst参照です。ポインタは定数ですが、intは定数ではありません。

ベクトルのタイプはvector<int const *>つまりvector<const int*>)である必要があります。この場合、要素はint const * const &を介してアクセスされます。

結論として、constnessはテンプレートでは推移的ですが、ポインターでは推移的ではありません。また、テンプレートにポインターを配置すると、両方の動作が少し得られます。

1
n.caillou