4

これは、私がやろうとしていることをうまく伝えているコードスニペットです:

void updatePointer(const int*& i)
{
  i++;
}

int main() {


  int array[5];
  int* arrayPtr = array;

  updatePointer(arrayPtr );
  return 0;
}

これにより、コンパイラ エラーが発生します。

prog.cpp: In function ‘int main()’:
prog.cpp:16: error: invalid initialization of reference of type ‘const int*&’ from
expression of type ‘int*’
prog.cpp:5: error: in passing argument 1 of ‘void updatePointer(const int*&)’
4

3 に答える 3

6

それができると仮定すると、次のように書くことができます。

const int c = 0;

void updatePointer(const int* &i) {
    i = &c;
}

int main() {
    int *ptr;
    updatePointer(ptr);
    *ptr = 1; // attempt to modify the const object c, undefined behavior
}

の目的constは、const-cast (または同等のもの) が含まれていない限り、ユーザー コードが const オブジェクトを変更できないようにすることです。したがって、コンパイラはこのコードを拒否する必要があります。aconst int*&から an へのバインドを禁止することint*は、上記のコードでコンパイラが拒否できる唯一の場所です。他のすべての行は問題ありません。

に暗黙的に変換できないのと同じ理由int**ですconst int **

const-safety の観点からの動機は別として、それが とint*は異なる型であるという観点から考えるとconst int*、たまたまそれに変換可能であると考えることができます。同様に、 に変換することはできますintdouble、 aを左辺値double&にバインドすることはできません。int実際にはint*const int*は同じサイズと表現を持っているのに対し、と はそうではないため、これが完全な理由ではintありdoubleません。そのため、const システムが壊れるという事実がなければ、それを許可する特別なケースが存在する可能性があります。

C++ に const と非 const の両方のオーバーロードがある理由strchrは、この問題に関連しています。関数updatePointerは、更新された値を返すのではなく、入力を変更しますが、原理は似ています。C スタイルのシングルstrchrを使用すると、キャストなしで const へのポインターを非 const へのポインターに「洗濯」することができます。これは、const システムの穴です。C++ (a) にはオーバーロードがあり、(b) C よりも厳密な型システムがあるため、その穴を塞いでいます。

updatePointer実際の関数を次のように動作させたい場合はstrchr、ポイントされているデータを調べて、ポインターの新しい値を計算すると、同じ状況になりますstrchr。問題は、新しいポインターに入力と同じ const 修飾を持たせたいことであるため、新しい値で何をするかに関係なく ( の場合はstrchrそれを返し、 の場合は書き戻す)。updatePointerconst および非 const オーバーロードまたは関数テンプレートのいずれかを提供する必要があります。

updatePointer指しているデータに関係なく、ポインターを特定の距離だけ移動するための実際の関数のみが必要な場合は、std::advance代わりに使用できます。

于 2012-09-26T11:32:37.957 に答える
5

あなたが書いたのは、const intへのポインタへの参照を取る関数です。あなたが求めているのは

updatePointer(int* const & i);

ただし、これはあまり意味がありません。ポインターへの参照を渡すことは、ポインターを変更するつもりであることを暗示しているように見えますが、const と宣言されているため変更できません。そのままでは、ポインタを次のように渡すだけで同じ効果が得られます

updatePointer(int* i);
于 2012-09-26T11:00:05.850 に答える
1

将来リンクが壊れた場合に備えて、ここにコピーしました

その理由付けは、理解するのが少し厄介です。主な質問は次のとおりです。「const int&」は「int」にバインドできるのに、「const int*&」を「int*」にバインドできないのはなぜですか?

基本的に、間接的なレベル (ポインター) を追加すると、ルールが変わります。単一レベルの間接参照 (単一の * など) を使用すると、ルールは次のように記述できます。

cv 修飾された型へのポインターへの参照は、cv 修飾がポインター (参照) の修飾よりも小さいか等しい同じ型の任意のものにバインドできます。(それを数回読んでください。)

したがって、「const int*&」を「int*」にバインドできないのは、「const int*」と「int*」が 2 つの異なる型であるためです (ルールの下線部分が壊れています)。

于 2012-09-26T11:02:08.227 に答える