2
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?

apaderno
  • 28,547
  • 16
  • 75
  • 90
Jayesh
  • 4,755
  • 9
  • 32
  • 62
  • 4
    your last snippet is clearly invalid, how would a compiler try to deduce the types? Once you declare a variable the compiler needs to know enough to deduce the type, storage and size. There is no information when you just type `auto i` – EdChum Aug 04 '17 at 08:49
  • 3
    The first two code snippets are not *exactly* equivalent, they just have similar effects for `int`s. If it instead was a class type with user defined constructors and assignment operators, the result could be totally different. – Bo Persson Aug 04 '17 at 08:53
  • 1
    `int i = 0;` is not equivalent to `int i; i = 0;`. The first defines `i` and initialises it with a value of `0`. The second defines `i` without initialisation, and then assigns it to `0`. – Peter Aug 04 '17 at 09:06
  • @EdChum: Simply said, the compiler could look at the rest of the block to determine the variables type or discard it completely. Other languages do that, C++ decided to go for a simpler model. – Deduplicator Aug 04 '17 at 10:24
  • @BoPersson Yes, if it used different types it might not be equivalent. Lucky it uses `int`, right? – Deduplicator Aug 04 '17 at 10:25
  • @Peter: Equivalent does not mean identical, but having the same result. And those snippets have that, if you don't forget applying the rules of the language. Naturally if it wasn't `int`, we might have a different situation. – Deduplicator Aug 04 '17 at 10:34
  • @Deduplicator - equivalent also means there is no difference of semantics. Semantically, `int i = 0` never involves `i` being uninitialised (it doesn't exist before that statement, and exists with a value zero afterward). Semantically, `int i; i = 0` creates `i` uninitialised, and then assigns it to zero. It is possible to, for example, `std::cout << i` before `i = 0` and trigger undefined behaviour. It is not possible to do that with `int i = 0`. – Peter Aug 04 '17 at 11:26
  • @Peter: The semantics of the snippets (using type `int`) are the same. The first one might consist only of a declaration with initializer, and the second of a declaration without initializer followed by an assignment, but that difference in expression is without consequence. – Deduplicator Aug 04 '17 at 12:01
  • @Deduplicator - rubbish – Peter Aug 04 '17 at 12:15
  • @Peter: If you say rubbish, **name the difference**. You can rewrite anything to do something completely different, but that doesn't say anything about what you had. – Deduplicator Aug 04 '17 at 13:16
  • 1
    @Deduplicator One is allowed in a `constexpr` function; the other isn't. – T.C. Aug 04 '17 at 14:36
  • @T.C.: Wow, there actually *is* a difference. Nice one, nobody got that one yet. – Deduplicator Aug 04 '17 at 14:43
  • I've closed as "not clear what you are asking". I assume you know that "int i = 0" is different from "auto i = 0" (auto vs int), yet you seem to imply that they are the same, because you say "But, [...]". Please clarify, so that I can discard the close-vote. – Johannes Schaub - litb Aug 04 '17 at 18:22
  • "If i put the pot on the hotplate, then fill in water and pull the pot off the plate and let it cool down. That is equivalent to not putting the pot on the hotplate in the first place. But, if i put a plastic pot on the hotplate, then fill in water and pull the pot off the plate, it all melts down. So why does it melt down, I thought it's equivalent to filling in water in a plastic pot without involving the hotplate, which I've done and works fine." – Johannes Schaub - litb Aug 04 '17 at 18:26

10 Answers10

7

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.

  • 1
    Well, they (`int i = 0;` and `int i; i = 0;`) *are* equivalent, though only after ploughing through quite a lot of verbiage. The as-if-rule does not only apply to the compiler, but also to interpreting natural language. – Deduplicator Aug 04 '17 at 09:12
  • 3
    @Deduplicator They are equivalent in sense "compilers are most likely to emit the same machine code", but not equivalent in terms of language syntax rules. Especially, when generalizing to types other than `int`, those expressions might not be equivalent in any sense. – el.pescado - нет войне Aug 04 '17 at 09:24
  • So, you concede they are equivalent, but insist on only looking at some generalization where that might no longer be true. Than just say that using this-and-that-generalization they are no longer equivalent. – Deduplicator Aug 04 '17 at 09:32
  • @Deduplicator - the "some generalization" that el.pescado mentioned that you are blithely dismissing is actually described by the C++ standard. That's the point you are repeatedly failing to acknowledge in your comments related to this question. The standard defines the language, including the meaning of various constructs and combinations of constructs, not the output from any compiler. – Peter Aug 04 '17 at 13:59
  • @Peter: I'm acknowledging that some generalized cases are not equivalent. That doesn't change that this case is, or that answering the question posed is worth it. And your persistent unwillingness to acknowledge that examining the specific case in question might have any value is quite boorish. – Deduplicator Aug 04 '17 at 14:09
  • 1
    In *this specific case*, where the type is `int` and the assignment is literally the next statement, the detectable effects will always be the same. That was @Deduplicator’s point with the as-if rule applying to natural language. If the type were `MyClass`, or the assignment didn’t immediately follow the initialization, then they wouldn’t be equivalent. – Daniel H Aug 04 '17 at 14:31
4

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
dlmeetei
  • 9,905
  • 3
  • 31
  • 38
3

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
2

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

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
2
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.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
1

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 =

Treebeard
  • 322
  • 1
  • 9
1

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.

Yuval Ben-Arie
  • 1,280
  • 9
  • 14
1

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.

msc
  • 33,420
  • 29
  • 119
  • 214
  • Your bold text "it must be assigned an initial value" is incorrect. It must be initialised. They are different things, even if the syntax looks similar (and can use the `=` character). – Peter Aug 04 '17 at 14:03
0

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.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • 1
    No, the two are not equivalent. Yes, they achieve the same net effect (defining a variable `i`, which will subsequently have a value of zero) but the means by which they get there differs. – Peter Aug 04 '17 at 09:40
  • @Peter: Don't confuse whether they get there the same way with whether they are equivalent. The as-if-rule is there for a reason! – Deduplicator Aug 04 '17 at 09:43
  • They are *potentially* equivalent. It's a dangerous mental model to take, as its not true for some types and some compilers. – Caleth Aug 04 '17 at 10:10
  • @Caleth: Equivalent is equivalent. Yes, it doesn't hold for many other more interesting types, but it does hold for trivial types. Which is the reason I spelled out the way they arrive at being equivalent, instead of just stating the bare fact. – Deduplicator Aug 04 '17 at 10:20
  • The 'As-if' rule doesn't *require* that these compile to the same object code. It only *permits* it. – Caleth Aug 04 '17 at 10:25
  • @Caleth: Yes, the exact same code may be compiled in innumerable different ways without violating the standard. Your point is? – Deduplicator Aug 04 '17 at 10:29
  • This specific example generalises *extremely poorly*. Changing it to an arbitrary type or an arbitrary value can very easily end up with observably different dynamic behaviour. Saying "We can trivially observe the final state of these, so by 'As-if' they are equivalent" may be *true*, but it isn't *helpful* – Caleth Aug 04 '17 at 10:40
  • @Caleth: I added "If we talked about different non-trivial types, the situation might be different." to explicitly call out that the generalization doesn't hold. Only considering some generalization isn't helpful, not considering generalization is generally also not helpful, but doing both most certainly is. While you shouldn't overlook the wood for trees, keep in mind there are trees! – Deduplicator Aug 04 '17 at 10:43
0
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.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252