auto în C++

Lasă compilatorul să deducă tipul variabilei din valoarea cu care este inițializată.

Sintaxă
auto nume = expresie;
auto& ref = expresie;
auto functie() { return ...; }   // C++14

Ce face auto

Cu auto nu mai scrii tipul: compilatorul îl află din valoarea de inițializare. auto x = 5; face din x un int, auto y = 2.5; un double. Tipul se fixează la compilare și nu se mai schimbă: C++ rămâne un limbaj cu tipuri stricte.

Este foarte util la tipuri lungi, ca iteratorii (auto it = harta.begin();), și în buclele for pe colecții. auto simplu face o copie și ignoră const și referința; scrie auto& sau const auto& când vrei referință.

Din C++14, o funcție poate avea tipul returnat auto, dedus din return. Înainte de C++11, cuvântul auto avea alt sens (variabilă locală automată) și nu era folosit aproape deloc.

Exemple

Exemplul 1: Tipuri deduse

std::is_same_v verifică la compilare dacă două tipuri sunt identice; aici îl folosim ca să vedem ce tip a dedus auto. Atenție: "Iași" devine const char*, nu std::string.

#include <print>
#include <string>
#include <type_traits>

int main() {
    auto a = 5;
    auto b = 2.5;
    auto c = "Iași";
    auto d = std::string("Iași");
    std::println("a e int: {}", std::is_same_v<decltype(a), int>);
    std::println("b e double: {}", std::is_same_v<decltype(b), double>);
    std::println("c e const char*: {}", std::is_same_v<decltype(c), const char*>);
    std::println("d e std::string: {}", std::is_same_v<decltype(d), std::string>);
}

Rezultat

a e int: true
b e double: true
c e const char*: true
d e std::string: true

Exemplul 2: auto cu iteratori și în bucle

Fără auto, iteratorul ar fi std::map<std::string, int>::iterator. Cu auto& în buclă modificăm chiar elementele, nu copii ale lor.

#include <map>
#include <print>
#include <string>

int main() {
    std::map<std::string, int> stoc = {{"mere", 10}, {"pere", 4}};
    auto it = stoc.find("pere");
    std::println("{}: {}", it->first, it->second);

    for (auto& [produs, cantitate] : stoc) {
        cantitate += 5;
    }
    for (const auto& [produs, cantitate] : stoc) {
        std::println("{} -> {}", produs, cantitate);
    }
}

Rezultat

pere: 4
mere -> 15
pere -> 9

Exemplul 3: Funcție cu tipul returnat dedus

#include <print>

auto media(int a, int b) {
    return (a + b) / 2.0;  // double, deci funcția returnează double
}

int main() {
    auto rezultat = media(9, 10);
    std::println("Media: {}", rezultat);
}

Rezultat

Media: 9.5

Greșeli frecvente

  • Scrii for (auto x : vector) și te miri că modificările nu rămân. auto face copii; folosește auto& ca să modifici elementele.
  • Declari auto x; fără valoare. Compilatorul nu are din ce deduce tipul și dă eroare.
  • Crezi că auto s = "text"; este un std::string. Este const char*; scrie std::string s = "text"; sau folosește sufixul "text"s.

Comenzi înrudite

  • decltype: Dă tipul exact al unei expresii, fără să o evalueze; util pentru a declara variabile „de același tip ca”.
  • range-for (for (x : colecție)): Parcurge pe rând toate elementele unei colecții (vector, tablou, string, map) fără index și fără iteratori scriși de mână.
  • structured bindings (auto [a, b]): Desface o pereche, un tuplu, o structură sau un tablou în variabile separate, cu nume, într-o singură declarație.
  • lambda ([](){}): O funcție fără nume, scrisă direct acolo unde e folosită; poate „captura” variabile din jur.
  • std::is_same: Verifică la compilare dacă două tipuri sunt exact același tip.