Syntaxes ...
A declaration is essentially read from right to left. Therefore,
T fubar;
Reads: name "fubar" is an object of type T.
T const fubar;
Reads: name "fubar" is a constant object of type T.
T * fubar;
Reads: name "fubar" is a pointer to constant object of type T.
T const * fubar;
Reads: name "fubar" is a pointer to constant object of type T.
T * const fubar;
Reads: name "fubar" is a constant pointer to object of type T.
T const * const fubar;
Reads: name "fubar" is a constant pointer to constant object of type T.
However, the standard allows a different (I presume older) style too, where the const about type is on the left:
const T fubar;
Reads: name "fubar" is a constant object of type T.
const T * fubar;
Reads: name "fubar" is a pointer to constant object of type T.
const T * const fubar;
Reads: name "fubar" is a constant pointer to constant object of type T.
These can have some constness too:
T fubar[N];
Reads: name "fubar" is an array of N type T objects.
T & fubar = gaz;
Reads: name "fubar" is a reference (alias) of type T object named "gaz".
T fubar( const U & gaz );
Reads: name "fubar" is a function that returns type T object by value and requires a parameter that it can create a reference to (const -- will not modify referred parameter).
For more fun:
T * foo;
, where T ==
U *
and U ==
int *
Is thus
int * * * foo;
and some of those could be const ...
And ...
1 2
|
int * foo[7]; // an array of 7 pointers (to integers)
int (*foo)[7]; // a pointer to an array of 7 integers
|
Besides, the whitespace in C/C++ is rather liberal, so preferred styles can and do differ:
1 2 3
|
T* bar;
T *bar;
T * bar;
|