int i = 0;
is equivalent to
int i;
i = 0;
Then,
auto i = 0;
It's OK, working fine. But,
auto i;
i = 0;
compiler gives an error.
So, Why compiler gives an error?
int i = 0;
is equivalent to
int i;
i = 0;
Then,
auto i = 0;
It's OK, working fine. But,
auto i;
i = 0;
compiler gives an error.
So, Why compiler gives an error?
It's not equivalent because auto
is not a type. In both examples, i
type is int
. auto
means that variable type is determined by type of expression it is initialized with (int this case, it's int
, as that's the type of literal 0
). That is,
auto i = 0;
is equivalent to:
int i = 0;
The snippet
auto i;
i = 0;
does not make sense, because there's no expression that compiler can deduce type from.
One could argue that compiler could look further to deduce type, but that would be extra effort for little value, so it's unlikely to make way into future C++ standards. And what type would be inferred in the following example:
auto i;
if (...)
i = 0;
else
i = "WAT?";
BTW, int i = 0;
is equivalent to int i; i = 0
but is not the same. First is initialization, second is default initialization followed by assignment. For types other than int
, namely classes with non-trivial constructors and/or assignment operators, the two snippets may not be equivalent.
The draft in section 7.1.6.4 auto specifier has this entry
The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer.
Hence, auto
and decltype(auto)
need an initializer.
auto i = 0; // ok, i is of type "int" deduced from 0's type
is equivalent to
int i = 0;
But
auto i; // error: no initializer, compiler fails to deduce type
i = 0; // error: consequent error, i not declared/defined
will not compile as compiler can not deduce the type of i
without the initializer.
Also,
int i = 0; // initialized i as 0
is different from
int i; // default initialized
i = 0; // invokes copy assignment
auto i
does not mean "i
can hold anything, so don't worry about what type it is". C++ requires that the type of any object must be known at the time that the object is created. When you write auto i = something;
the compiler looks at the type of something
to figure out what the type of i
should be. If there is no something
there is nothing that tells the compiler what the type of i
should be, and you get an error.
the code
auto i;
i = 0;
should not even compile because type of i
cannot be determined at compilation time as there's no direct assignment as in your former example, therefore compiler will not know what to substitute auto
for i
with. In you first example, where you had auto i = 0;
, the direct assignment tells the compiler i
should be of integer
type.
Docs
auto i;
i = 0;
Will not work since auto
deduces the type of i
from its initializer and in this case you have no initializer.
On the other hand, this works:
auto i = 0;
Because now you do have an initializer - 0
- and since the type of a literal 0
is int
that's what auto
deduces the type of i
to be.
Auto type needs to be deducable by the compiler and once type set it cant be changed. It's a compile time operation. Therefore it needs initialization. This is actually the point in it, ensure variable initialization by moving everything to the right hand side of the =
auto
just means the compiler will infer the type. You don't give it any information, up until that line, it can use to decide the type and size required.
When a variable is defined with auto
, it must be assigned an initial value. Otherwise there would be no way to determine its type, because the type of a variable declared auto
is statically determined by the compiler.
C++11 standard:
7.1.6.4 auto specifier
...
3 Otherwise, the type of the variable is deduced from its initializer. The name of the variable being declared shall not appear in the initializer expression.
Yes, the following two are equivalent where allowed, due to the specific type used.
The second one is forbidden in constexpr
-functions though (Thanks @T.C.):
int i = 0;
int i;
i = 0;
Though they use different means to arrive there (copy-initialization vs. default-initialization degenerating to no-initialization combined with assignment), the as-if-rule means they are equivalent. If we talked about different non-trivial types, the situation might be different.
Now, if we substitute auto
for int
, things get more complicated:
No longer do we name the concrete type of our variable, but we let the compiler deduce it.
And the standard states that it will only deduce it from an initializer, which must be part of the declaration.
It could easily look slightly further afield, maybe at least the way return-type-deduction works for lambdas and C++14 functions, meaning to the first assignment.
Or it could even try to synthesise a compatible type from all places it is used, like some other languages do it, but that would complicate the rules quite a lot.
Anyway, the standard does not allow doing so, and it has the last word on what is and isn't C++, so there we are until and unless someone makes a compelling case to the committee to change it in the next version of the language.
int i;
i = 0;
and
int i=0;
give same observable result, but they are not equivalent. The former first declares a variable and they assign a value to it, the latter declares a variable and initializes it. So it is in fact equivalent to int i(0);
If you were using more complex classes instead of plain integers, the former code would invoke operator =
, while the latter would invoke a copy (or move) constructor.
That's the reason why auto i=0;
makes sense: it defines a variable i
of the same type its initializer (here a plain int
). But auto i;
raises a compilation error because at the time the compiler processes the declaration, it does not know what the type should be.