前書き
主に自分用。まァ役に立てればなによりですが。
内容
参照
参照とポインタ
参照はオブジェクトではないので、参照へのポインタは定義できません。
int num, &ref = num, &*ptrToRef = &ref; // エラー
ポインタはオブジェクトなので、ポインタへの参照は定義できます。
int num, *ptr = &num, *&refToPtr = ptr; // OK
const
extern
について
複数のファイルに亘って同じ定数を使う場合は、個々のファイルにそれぞれ定義を書きます。
const int alpha = 12;
int beta = alpha * 2;
const int alpha = 12;
int gamma = alpha / 3;
一つのファイルだけに定数の定義を書き、他のファイルには宣言だけ書くこともできます。extern
を使うのですが、宣言だけでなく、定義にも使います。
extern const int alpha = 12;
int beta = alpha * 2;
extern const int alpha;
int gamma = alpha / 3;
const
への参照
const
への参照で変数への参照を初期化することはできません。
int var = 7;
const int con = 8;
const int &ref0 = con;
int &ref1 = con; // エラー
型さえ合っていれば、何ででも const
への参照を初期化することができます。
int a = 0;
const int &ref0 = 0;
const int &ref1 = a;
const int &ref2 = a + 1;
const
なポインタと const
を指すポインタ
const
が来る位置で色々決まります。
int i = 0;
const int *a = &i; // const を指すポインタ (所謂 low-level const)
int *const b = &i; // const なポインタ (所謂 top-level const)
const int *const c = &i; // const を指す const なポインタ
top-level const
とはそのオブジェクト自体が const
であることを意味します。だから、top-level const
を持つオブジェクトの値を変えることは出来ません。
low-level const
とはそのポインタが指すオブジェクト、またはその参照が指すオブジェクトが const
であることを意味します。
constexpr
constexpr
で宣言されたオブジェクトは返り値の変わらない式で初期化されなければいけません。constexpr
で宣言されたオブジェクトは top-level const
になります。
constexpr int *ptr0 = nullptr; // const なポインタ
constexpr const int *ptr1 = nullptr; // const を指す const なポインタ
typedef
typedef
を使って長い型指定子を好きな型指定子に名前を変えることができます。
typedef double dd, *dptr, &dref;
dd pi = 3.14; // pi は double
dptr piptr = π // piptr は double を指すポインタ
dref piref = pi; // piref は double への参照
C++11 では using
を使って似たようなことができます。
using dd = double; // double
using dptr = double*; // double を指すポインタ
using dref = double&; // double への参照
typedef
した型指定子の前に const
を付けると top-level const
となります。
typedef double dd, *dptr;
dd a = 0;
const dptr p = &a; // double を指す const なポインタ
auto
auto
を使った宣言で、初期化子が参照だと、型指定子は参照が指すオブジェクトの型となります。参照にしたい場合、識別子の前に &
を書きます。
int a = 0, &r = a;
auto n = r; // int
auto &n = r; // int への参照
また、auto
を使うと、初期化子の top-level const
がなくなります。low-level const
は残ります。top-level const
にしたい場合は、const auto
と書きます。
const int c = 0, &r = c; // top-level const な c と low-level const な参照 r
auto d = c; // int (top-level const がなくなった)
auto e = r; // int (参照から const int へ変わり、top-level const がなくなった)
auto f = &c; // const int を指すポインタ (&c は low-level const なので)
const auto g = c; // const int (const auto による top-level const 指定)
decltype
decltype
は top-level const
も参照もそのまま型指定子となります。
const int a, &ref = a;
decltype(a) i = 12; // const int
decltype(ref) r = a; // const int への参照
左辺値も左辺値のままだったり。
int a, *ptr = &a;
decltype(*ptr) ref = a; // *ptr は int ではなく int への参照 (左辺値)
decltype
に通す変数名に括弧を付けると、それは式として評価されます。括弧を付けなければ、単純に変数として通されます。式として評価されると、変数は参照に変わります。
int a = 9, &r = a;
decltype((a)) ref = a; // int への参照
decltype(a) num = 0; // int
decltype(r) rref = a; // int への参照 (r がもともと参照なので)