when I declare C++ variables, I do it like this:
int a,b,c,d;
or
string strA,strB,strC,strD;
I.e., first the type then a comma separated list of variable names.
However, I declare pointers like this:
int *a,*b,*c,*d;
and references like this:
int &a,&b,&c,&d;
To be consistent it should be
int* a,b,c,d;
and
int& a,b,c,d;
Why is it not consistent?
It's because of the C heritage. The
*
modifier applies to the variable in C. So the C++ designers made&
to apply to the variable as well by analogy, since they couldn't change the first without breaking C compatibility. Same is true for the array syntax too:In The Design and Evolution of C++ Bjarne Stroustrup says he wasn't happy with this but had to accept it for C compatibility. He was unhappy with this in particular:
It's not clear from the declaration if
a
is a pointer to an array or an array of pointers (it's an array of pointers, you need brackets to override).Of course, you can always use a
typedef
to clean things up a little.The best answer I've seen as to why things like
*
apply to variables and not to types is the idea that declaration should follow use.Basically, how you declare a variable should look similar to how you use a variable.
For example,
...the use of
a
andb
looks similar to the declaration ofa
andb
.There's even a citation for this behavior from Dennis Ritchie, one of the creators of C:
C++ has inherited this syntax from C. The K&R book (§5.1) says that the expression
is intended to be mnemonic (i.e. you read “
*ip
and**ipp
have typeint
”), they wanted it to mimic usage syntax.I agree it is quite cryptic and counterintuitive for humans, and inconsistent with typedefs, e.g.
but it never really was C++ author's decision, the choice to make the language compatible with C implied using this syntax, that's why.
C has a rule for its declarations: Declarations mimic use. What this means is that the declaration for a variable looks like the way the variable is used. For example:
Using this variable looks like
i
, and that expression results in anint
.Using this variable looks like
*i
, and that expression results in anint
. This also implies that an expressioni
results in a pointer to anint
.Using this variable looks like
i()
, and results in anint
. This also impliesi
is a function that takes nothing and that returns anint
.Using this variable looks like
(*i[x])()
, and results in anint
. This also implies*i[x]
is a function returningint
, andi[x]
is a pointer to a function returningint
, andi
is an array of pointers to functions returningint
.So:
declares several expressions which all have the type
int
, but the variables themselves are not allint
s.N.B. in declarations of function and arrays the sub declarations don't literally resemble the use of the variable. I.e.
int i[5];
doesn't mean that you need to put a '5' inside the square brackets when you usei
, andint i(int);
doesn't mean you call the function by sayingi(int);
. Also declarations of variables of struct types don't match their use since you'd have to declare expressions for each member variable.Related to the syntax for declaring variables is that of typedefs. To declare a typedef with a certain type, you use the same syntax as for declaring a variable of the desired type, but you stick
typedef
in front of the declaration and the variable name becomes the typedef name.C++ adds references, templates, pointers to member, and a bunch of stuff. It tries to some extent to follow the old C convention, but that convention doesn't really work all that well for many of the things C++ adds, so you do start getting inconsistencies. You'll just have to learn the idiosyncrasies and chalk it up to an imperfect marriage between C and C++.
The reason is: in reality
&
and*
in C and C++ applies to variable and no to type.So the problem is that if you want to declare 4 pointer to integers you should write
Writing
int* a, b;
meansFor this reason a lot of people prefer to write
int *a;
thanint* a;
, just code style.Of course
int*
is a type, but the C syntax states clearly that in a variable declaration*
and&
will apply to variable.This happens for the same reason that arrays in C are declared in this way:
In other languages like C# instead the syntax
int[] array;
is used.Another thing is the pointer to function syntax:
We are applying the
*
to the variable name.It seems to me that the use of
*
and&
applied to the variable, also if 90% of us would prefer differently, is more consistent with the rest of the language.In the same way, going back to arrays: