Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 6 of 8

auto tells the compiler to work out a variable's type from what you assign to it:

#include <iostream>

int main() {
    auto count = 42;
    auto price = 19.99;
    auto letter = 'A';
    auto ready = true;

    std::cout << count << " " << price << " " << letter << " " << ready << "\n";
    std::cout << sizeof(count) << " " << sizeof(price) << "\n";
    return 0;
}
42 19.99 A 1
4 8

This is not dynamic typing. count is exactly as much an int as if you'd written int, and it can never hold anything else. The type is fixed at compile time — you just didn't have to type it.

Because the type comes from the initializer, auto without one is an error:

// WILL NOT COMPILE
int main() {
    auto x;      // deduce from what?
    x = 5;
    return 0;
}

That's a feature: it makes the uninitialized-variable bug from lesson 3.1 impossible.

Where auto earns its place

Nobody needs auto for int. It pays off when the type is long, mechanical, and adds nothing:

#include <iostream>
#include <map>
#include <string>
#include <vector>

int main() {
    std::map<std::string, std::vector<int>> scores;
    scores["ada"] = {95, 88};
    scores["grace"] = {91};

    for (auto it = scores.begin(); it != scores.end(); ++it) {
        std::cout << it->first << ": " << it->second.size() << "\n";
    }
    return 0;
}
ada: 2
grace: 1

Written out, that iterator's type is std::map<std::string, std::vector<int>>::iterator. Spelling it adds no information — the reader already knows it's an iterator over scores — and if you later change the container, every one of those spelled-out types needs editing. With auto, they don't.

This is the core argument: auto removes types that are derivable and noisy, not types that are informative.

Where auto hides too much

auto value = getConfig();

What is value? An int? A std::string? An object that owns a file handle? The reader has to go find getConfig's declaration. If the function name doesn't make the type obvious, writing it out is kinder.

Two more specific traps:

Literals may not be the type you assume.

#include <iostream>

int main() {
    auto x = 5;      // int
    auto y = 5.0;    // double
    auto z = 5.0f;   // float
    auto w = 5u;     // unsigned int

    std::cout << sizeof(x) << " " << sizeof(y) << " "
              << sizeof(z) << " " << sizeof(w) << "\n";
    return 0;
}
4 8 4 4

auto x = 5; gives int — so if you needed a double, you silently got integer division later.

auto drops references and const by default.

#include <iostream>
#include <string>

int main() {
    std::string original = "hello";
    auto copy = original;        // a full copy, not a reference
    copy += " world";

    std::cout << original << "\n";
    std::cout << copy << "\n";

    auto& ref = original;        // now a reference
    ref += "!";
    std::cout << original << "\n";
    return 0;
}
hello
hello world
hello!

auto copy = original; copies the whole string — a silent performance cost on large objects. When you want a reference, say auto&; when you want a read-only reference, const auto&. Module 7 covers references properly; for now just know that plain auto means a copy.

Practical guidance

Use auto when:

  • The type is long and mechanical — iterators, lambdas (Module 14), template results.
  • The type is obvious from the same line: auto count = static_cast<int>(v.size());
  • Spelling it would force an unwanted conversion.

Write the type when:

  • It's short and meaningful: int, double, std::string.
  • The reader needs it to understand what's happening.
  • You specifically need a type the initializer wouldn't give you.

Teams differ on this — some use auto almost everywhere, others sparingly. Both work. What doesn't work is being inconsistent within one codebase.

Try it

Predict the type auto deduces in each case, then verify with sizeof: auto a = 10;, auto b = 10.0;, auto c = '1';, auto d = 10 / 3;, auto e = 10.0 / 3;

Checkpoint

  • auto deduces a type at compile time from the initializer — it is not dynamic typing.
  • auto requires an initializer, which conveniently makes uninitialized variables impossible.
  • Use it for long mechanical types like iterators; spell out short meaningful ones.
  • Integer literals deduce to int — auto x = 5; is never a double.
  • Plain auto copies and drops const; use auto& or const auto& for references.

Questions about this lesson

Log in to ask a question.