const
はどういう意味ですか?読み取り専用は私にとってその意味をカプセル化しているようですが、私が正しいかどうかはわかりません。
読み取り専用とconst
が異なる場合、誰かが理由を教えてもらえますか?
この質問のきっかけとなったのは this answer であり、const
"just"はCでは読み取り専用を意味します。これはallconst
は、CであるかC++であるかに関係なく、意味します。彼はどういう意味ですか?
CとC++でのconst
の具体的な違いに対する回答として、新しい質問を作成しました: 「const」はCとC++でどのように異なりますか? Rと同じです。さんの提案。
変数をconst
として宣言することで、その変数を変更する意図がないことをコンパイラーに示します。しかし、それは他の人が持っていないわけではありません!これは、最適化を可能にし、コンパイルエラーによって通知されるようにするためです(注:ほとんどの場合はコンパイルエラーですが、const == ReadOnly
はランタイムエラーを意味します)。
const
は読み取り専用を意味しません。const volatile
を記述できるため、いつでもそれ自体で変更される可能性がありますが、私はそれを変更するつもりはありません。
編集:これは古典的な例です:メモリマップされたポートから現在の時間を読み取るコードを書いていると考えてください。 RTCがメモリDWORD 0x1234にマップされていることを考慮してください。
const volatile DWORD* now = (DWORD*)0x1234;
これはconst
です。これは、読み取り専用のポートであるためです。また、volatile
は、読み取るたびに変更されるためです。
また、多くのアーキテクチャでは、グローバル変数を変更するのはUBであるため、グローバル変数をconst
として効果的に読み取り専用にしています。これらの場合、UBは実行時エラーとして現れます。他の場合では、それは本当のUBになります:)
これは良い読みです: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
コンパイラは、const
として宣言されたものを変更することを許可しません。あなたの言う通りです。
これは主に関数プロトタイプで使用され、関数がこれに触れないこと、またはポインターが渡されたときにそのことをユーザーに通知します。それはまたあなた自身にとって一種のフェイルセーフとして機能します。
多くの人がconst
は変更できないことを意味すると言っています。あれは 明らかに偽り。 const
は簡単にキャストできます。このスニペットに注意してください:
void foo(const int *somevalue)
{
int *p = (int*) somevalue;
*p = 256; // OMG I AM EVIL!!!!11
}
コンパイラはこれをやめさせません。では、const
の目的は何でしょうか。私はそれをもっと提案と呼んでいます。関数が期待するコントラクトの関数プロトタイプを見て、それを思い出させます。あなたが不注意にそれを壊すなら、あなたのコンパイラはあなたに怒鳴ります。 (ただし、上記のキャストのように意図的に壊した場合は除きます。)
場合によっては、標準が意図的にconst
を壊しています。たとえば、strstr
の戻り値に注意してください。定義により、提供するconst
バッファーにオフセットが返されます...しかし、戻り値はconst
ではありません。どうして?まあ、これは、strstr
以外のバッファでconst
の戻り値を使用すると、意味のある中断を引き起こします。
2バイトごとに同一(コメントを除く)の最小ケースの例...
最初にCで、gccは警告を出します...
/*関数は、 2つの読み取り専用整数の配列へのポインタを取ります。*/ void a(const int(* parray)[2]); void b(void) { int array [2] = {1,2}; const int crray [2] = {1,2 }; /* Cはこれを読み取り専用の場所に隠しておく権利を留保します。*/ a(&array); /*警告:互換性のないポインタタイプから「a」の引数1を渡します*/ a(&crray); /* OK!*/ }
C++でも同じことが言えます... g ++はそれでかなり満足しています。
//変更しないことが約束されている2つの整数の配列 //へのポインターを受け取る関数。 //(constnessをキャストしない限り;-P) void a(const int(* parray)[2]); void b( void) { int array [2] = {1,2}; const int crray [2] = {1,2}; a(&array); // C++はこれで問題ありません。 a(&crray); // OK! }
const char * hello_1{ "Hello!" };
const char hello_2[]{ "Hello!" };
char * ptr{};
// take away the const-nes
// ptr = (char *)hello_1;
// *ptr = '*'; <-- write access violation
// hello_1 is in a read only memory
// take away the const-nes
ptr = (char *)hello_2;
*ptr = '*'; // <-- OK
// hello_2 is modifiable
ポインタはメモリを指し、char *
は読み取り専用のデータセグメント内のメモリを指します。 char *
とchar []
の違いは、どちらもデータセグメントで同じように宣言されている一方で、char []
は、使用されている場合はスタックにプッシュされるため、読み取り可能として扱われることです。