18

Since C++11 we can use auto a = 1+2 instead of int a = 1+2 and the compiler deduces the type of a by itself. How does it work? Is it slower during compile time (more operations) than declaring the type myself?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • 1
    Have you tried measuring codes with and without `auto`? Related: http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/ – CinCout Sep 11 '15 at 08:37
  • 4
    This is a compile-type specifier, it does not affect the running time. – Marius Bancila Sep 11 '15 at 08:50
  • 1
    I meant slower compile time – CIsForCookies Sep 11 '15 at 08:54
  • @CIsForCookies: That depends on your compiler! – Kerrek SB Sep 11 '15 at 09:03
  • 7
    I doubt it would amount to much, to be honest, because the compiler has to deduce the "ideal" expression type anyways to make sure it is compatible with the *declared type*. So I would imagine implementing *auto* likely builds on a lot of what the compiler is doing already. – Galik Sep 11 '15 at 09:13
  • Considering how _extremely_ common integers are, and their role in Integer Constant Expressions, I wouldn't be surprised if compilers had separate paths for "integral expressions" and "every other type of expression". – MSalters Sep 11 '15 at 11:06
  • 2
    `auto` is only legal where the type can be inferred from an expression, and the compiler must determine the expression's type anyway to validate whether the assignment (to non-`auto`) is valid. **On the other hand**, using `auto` implies that no implicit conversions take place, nor does the compiler need to validate whether narrowing conversions etc. happen. Thus, `auto` may very well _compile faster_. It might even be faster at runtime, in some odd cases (where conversions are otherwise made due to the programmer's choice of type). – Damon Sep 12 '15 at 10:31

3 Answers3

18

auto is asking the C++11 compiler to make some limited kind of type inference (look into Ocaml if you want some more sexy type inference language). But the overhead is compile-time only.

If you replace auto a=1+2; with int a=1+2; (both have the same meaning, see answer by simplicis) and if you ask your compiler to optimize (and probably even without asking for optimizations) you'll probably get the same machine code. See also this.

If using GCC try to compile a small C++11 foo.cc file with g++ -Wall -fverbose-asm -O -S foo.cc and look (with an editor) into the generated foo.s assembler file. You'll see no difference in the generated code (but the assembler file might perhaps change slightly, e.g. because of metadata like debug information etc.)

If you are concerned about slower compile-time I guess that using auto is not a decisive factor (probably, overloading could be more costly in compilation time). C++11 is nearly designed to practically require a lot of optimizations (in particular sophisticated inlining and constant folding and dead code elimination), and its "parsing" (notably header inclusion and template expansion) is costly.

Precompiling headers and parallel builds with make -j (and perhaps ccache or distcc) might help in improving the overall compilation time, much more than avoiding auto.

And if you wanted to systematically avoid auto (in particular in range-for loops like std::map<std::string,int> dict; for (auto it: dict) {...}) you'll end up typing much more source code (whose parsing and checking takes significant time) with more risks of error. As explained here, you might guess slightly wrongly the type, and expliciting it (slightly wrongly) might slow down the execution of your code because of additional conversions.

If using GCC you might pass the -ftime-report to g++ and get time measurements about various GCC passes and phases.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    What has `auto` to do with compiler optimisations? The meaning of `auto` is prescribed by the language, and `auto a = 1 + 2;` means exactly the same as `int a = 1 + 2;`. – Kerrek SB Sep 11 '15 at 09:04
  • Indeed, so what? A C++ compiler *practically* needs to optimize a lot. – Basile Starynkevitch Sep 11 '15 at 09:06
  • 2
    Yes,. but that seems unrelated to the topic of this question. – Kerrek SB Sep 11 '15 at 09:07
  • 1
    By the way, placeholder types (and templates/values) are getting polished with Concepts, so I wouldn't refer to OCaml for sexy type inference, but to [N4377](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4377.pdf). – Columbo Sep 11 '15 at 09:36
  • Well, I still find Ocaml's type inference more sexy. It is a matter of taste. – Basile Starynkevitch Sep 11 '15 at 09:38
9

The compiler knows the type an expression (like 1 + 2) evaluates to. That's just the way the language works -- both operands are of type int so the result is int as well. With auto a, you are just telling the compiler to "use the type of the initializing expression".

The compiler does not have to do any additional work or deducing here. The auto keyword is merely relieving you from figuring out the expression and writing the correct type. (Which you might get wrong, with probably unintended side-effects -- see this question (and the top answer) for an example how auto can avoid unintended run-time conversions and copying.


The auto keyword really comes into its own with iterators:

std::vector< std::string >::const_iterator it = foo.cbegin();

versus

auto it = foo.cbegin();
Community
  • 1
  • 1
DevSolar
  • 67,862
  • 21
  • 134
  • 209
6

How does it work:

From the ISO/IEC:

...The auto specifier is a placeholder for a type to be deduced (7.1.6.4). The other simple-type-specifiers specify either a previously-declared user-defined type or one of the fundamental types...

7.1.6.4 auto specifier

  1. The auto type-specifier signifies that the type of a variable being declared shall be deduced from its initializer or that a function declarator shall include a trailing-return-type.
  2. The auto type-specifier may appear with a function declarator with a trailing-return-type in any context where such a declarator is valid.
  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. This use of auto is allowed when declaring variables in a block, in namespace scope, and in a for-init-statement; auto shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-specifier-seq shall be followed by one or more initdeclarators, each of which shall have a non-empty initializer...

Example:

auto x = 5; // OK: x has type int
const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
static auto y = 0.0; // OK: y has type double
auto int r; // error: auto is not a storage-class-specifier

Is it faster:

The simple answer is Yes, by using it a lot of type conversions could be omitted, however, if not used properly it could become great source of errors.

In one of the interviews from Bjarne Stroustrup, he said that auto keyword has resulted in win-win situation for coders and compiler implementers.

Ziezi
  • 6,375
  • 3
  • 39
  • 49
  • 1
    I'm very surprised by this. I imagined auto will take a bit more compile time but will be easier for me to write. If what you say is true, why not use auto all the time? It would not allow uninitialized variables -> less room for error, and it is easier to write and faster – CIsForCookies Sep 11 '15 at 09:59
  • 2
    @CIsForCookies well, probably not all the time, but definitely in all the cases that are allowed. In my opinion, it is a great language feature and one should incorporate it in his "dictionary". – Ziezi Sep 11 '15 at 10:15