C++ のポインターで const 修飾子を使用する
この記事では、C++ でポインタを用いて const
修飾子を使用する方法について、複数の方法を示します。
C++ で読み取り専用オブジェクトを宣言するために const type var
記法を使用する
C++ では、読み取り専用(不変)として定義する必要のあるオブジェクトの修飾子として const
というキーワードを提供しています。const
変数は const type var
または type const var
という表記法で宣言されますが、どちらも構文的には正しいのですが、前者が従来のスタイルとして用いられます。const
の修飾オブジェクトは変更ではないので、宣言の間に初期化されなければなりません。これにより const int number;
- は無効になり、コンパイラエラーが発生します(おそらくあなたの IDE もそれについて悲鳴を上げるでしょう)。
変数 const
が初期化されると、実行時に別の値を代入することはできません。したがって、次の例の main
関数の 3 行目は無効であり、コンパイラはこれを処理しません。同じ型の変数へのポインタを宣言した後に const
変数のアドレスをそれに代入しようとすると、コンパイラによってエラーが報告されることに注意してください。後者のエラーは、-fpermissive
フラグを指定してコンパイルした場合、通常はオーバーライドされることに注意してください。
#include <iostream>
int main() {
const int number = 1234;
number = 235; // Error
int *ptr = &number; // Error
return 0;
}
C++ で読み取り専用オブジェクトを扱うためにポインタを用いて const
修飾子を使用する
const
修飾子はポインタと一緒によく使われます。宣言には const type * var
、type *const var
、const type *const var
の三種類があります。1つ目は、var
ポインタを読み取り専用の type
オブジェクトへの var
ポインタとして宣言するもので、オブジェクトは変更できないがポインタ自体は変更できることを意味します。2つ目は var
読み取り専用の type
オブジェクトへのポインタであり、ここでは一意であり、変更可能なオブジェクトへの不変のポインタを宣言し、最後のものはポインタとオブジェクトの両方を不変であると定義しています。
これらの表記法は複数の有用な機能を提供し、以下のコードサンプルで説明します。最後の例で示されているように、const
変数のアドレスを const 以外のポインタに格納することはできませんでしたが、const 指定子を追加すれば操作は有効になります。しかし、main
ループの 4 行目で示されているように、新たに宣言されたポインタを介して格納された値を変更することはできないことに注意してください。
#include <iostream>
using std::cout;
using std::endl;
#define STR(num) #num
int main() {
const int number = 1234;
const int *c_ptr = &number;
// *c_ptr = 42; // Error
cout << STR(number) << " - " << number << endl;
cout << STR(*c_ptr) << " - " << *c_ptr << endl;
return 0;
}
出力:
number - 1234
*c_ptr - 1234
ポインタで const
修飾子を使っている間のもう一つの共通の問題は、読み込み専用のオブジェクトを指すポインタへの非 const ポインタの代入です。次のコード例では新しい nonconst 変数 number2
が初期化されており、const
オブジェクトへのポインタとして宣言されていた c_ptr
が number2
のアドレスで代入されていることに注意してください。この操作は C++ では有効であり、結果として number2
変数に格納されている値を c_ptr
を介してのみ読み込むことができますが、変更を加えるとコンパイラエラーが発生します。
#include <iostream>
using std::cout;
using std::endl;
#define STR(num) #num
int main() {
const int number = 1234;
const int *c_ptr = &number;
int number2 = 3456;
c_ptr = &number2;
// *c_ptr += 12; // Error
number2 += 12;
cout << STR(number) << " - " << number2 << endl;
cout << STR(*c_ptr) << " - " << *c_ptr << endl;
return 0;
}
出力:
number2 - 3468
*c_ptr - 3468