それができると仮定すると、次のように書くことができます。
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*
、たまたまそれに変換可能であると考えることができます。同様に、 に変換することはできますint
がdouble
、 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
それを返し、 の場合は書き戻す)。updatePointer
const および非 const オーバーロードまたは関数テンプレートのいずれかを提供する必要があります。
updatePointer
指しているデータに関係なく、ポインターを特定の距離だけ移動するための実際の関数のみが必要な場合は、std::advance
代わりに使用できます。