Menuliskan tipe secara eksplisit memang disiplin yang baik, tetapi ada situasi di mana tipe itu panjang, repetitif, atau bahkan sulit ditulis dengan benar. Kata kunci auto — resmi untuk keperluan ini sejak C++11 — memindahkan pekerjaan itu kepada compiler: kita menulis auto nama = nilai;, dan compiler menetapkan tipe nama persis dari nilai yang kita berikan. Bukan keajaiban dan bukan tipe “apa saja”: deduksi auto punya aturan yang tegas, dan memahami aturannya penting karena ada kasus di mana const atau reference ternyata tidak ikut terbawa. Chapter ini membedah aturan itu lewat program teruji, syarat wajib initializer, dan mengakhiri dengan sekilas pandang decltype sebagai pasangannya.

auto untuk Variabel #

Sebelum membaca contoh, satu konteks singkat: baris int& aliasUmur = umur; di bawah membuat reference — nama lain untuk variabel yang sama, bukan salinan — yang pembahasannya tuntas di Section Pointer dan Reference. Kita memakainya di sini hanya untuk membuktikan bagaimana auto memperlakukannya. Sekarang programnya:

cpp
#include <iostream>
#include <string>

int main() {
    int umur = 20;
    const int batasUsia = 100;

    auto a = umur;        // int: salinan dari umur
    auto b = batasUsia;   // int: const tidak terbawa ke salinan
    auto c = 3.14;        // double
    auto d = 10u;         // unsigned int
    auto e = "C++23";     // const char*: string literal, BUKAN std::string
    auto f = std::string{"auto"};

    int& aliasUmur = umur;           // reference: nama lain untuk umur
    auto g = aliasUmur;              // int: reference ikut hilang saat disalin
    auto& rUmur = aliasUmur;         // int&: auto& mempertahankan reference
    const auto& rBatas = batasUsia;  // const int&: const terjaga lewat referensi

    decltype(batasUsia) salinanBatas = batasUsia;  // const int: dipertahankan persis

    b = 150;              // sah: b hanyalah int biasa

    std::cout << "a       = " << a << "\n";
    std::cout << "b       = " << b << "\n";
    std::cout << "c       = " << c << "\n";
    std::cout << "d       = " << d << "\n";
    std::cout << "e       = " << e << "\n";
    std::cout << "f       = " << f << "\n";
    std::cout << "g       = " << g << "\n";
    std::cout << "rUmur   = " << rUmur << "\n";
    std::cout << "rBatas  = " << rBatas << "\n";
    std::cout << "salinan = " << salinanBatas << "\n";

    return 0;
}

Output yang Dihasilkan:

text
a       = 20
b       = 150
c       = 3.14
d       = 10
e       = C++23
f       = auto
g       = 20
rUmur   = 20
rBatas  = 100
salinan = 100

Setiap variabel auto di atas menerima tipe dari initializer-nya: a dari int, c dari literal 3.14 yang bertipe double, d dari literal 10u yang bertipe unsigned int (tercetak 10, sebagaimana perilaku tampilan unsigned), dan f dari std::string. Baris b = 150; adalah bukti perilaku paling penting: b dideduksi dari batasUsia yang const, tetapi yang terdeduksi hanyalah int biasa — assignment justru berhasil dan b berubah menjadi 150.

Aturan Deduksi auto #

Perilaku di atas bukan acakan; standar menetapkannya dengan aturan yang bisa diringkas untuk variabel:

  • auto x = nilai; membuat salinan: tipe x adalah tipe nilai setelah referensi dan const tingkat teratas dilepas. Karena itu auto b = batasUsia; menghasilkan int — kita mendapat salinan yang boleh diubah, bukan cermin dari variabel const-nya.
  • Reference ikut hilang saat disalin: auto g = aliasUmur; menghasilkan int, bukan int&. Salinan memang salinan; mengubah g tidak menyentuh umur.
  • auto& mempertahankan reference: menambahkan & memaksa deduksi mengikuti bentuk referensi, sehingga rUmur adalah nama lain yang nyata untuk umur.
  • const auto& menjaga const: rBatas bertipe const int&; melalui nama ini, batasUsia tetap tidak bisa diubah.
  • Tipe mengikuti literal apa adanya: 3.14 berarti double (bukan float), 10u berarti unsigned int, dan "C++23" berarti const char* — string literal bertipe karakter mentah, bukan std::string. Itulah jebakan auto e yang paling sering menggigit pemula; jika ingin std::string, tulis eksplisit atau pakai std::string{"..."}.

Aturan “reference dan const hilang pada salinan” ini sebenarnya pindahan dari aturan konversi yang sama yang kita temui pada Chapter Signed dan Unsigned: compiler mengikuti aturan baku bahasa, dan auto hanya menerapkannya secara konsisten. Konsekuensi praktisnya: gunakan auto saat Anda memang sengaja menginginkan salinan, dan pakai auto& atau const auto& ketika ingin berbagi objek yang sama.

auto Wajib Punya Initializer #

Deduksi bekerja dengan cara membaca nilai awal, sehingga auto tanpa initializer tidak punya bahan berpikir dan compiler langsung menolaknya:

cpp
int main() {
    auto x;
    return 0;
}

Pesan yang dihasilkan g++:

text
auto-noinit.cpp: In function ‘int main()’:
auto-noinit.cpp:2:5: error: declaration of ‘auto x’ has no initializer
    2 |     auto x;
      |     ^~~~

Syarat ini sebenarnya menyelamatkan kita dari masalah lama: variabel yang dideklarasikan tanpa nilai (Chapter Deklarasi Variabel). Dengan auto, lupa memberi nilai awal tidak lagi mungkin lolos diam-diam — compiler menjadi penjaga yang memaksa pola “deklarasi sekaligus inisialisasi” yang kita anjurkan sejak awal section ini.

decltype: Deduksi Tanpa Menyalin #

auto punya pasangan bernama decltype. Bila auto mengambil tipe dari nilai initializer (lalu melepas reference dan const), decltype(nama) mengambil tipe persis seperti yang dideklarasikan untuk nama itu — const dan segalanya ikut. Pada contoh utama tadi, decltype(batasUsia) salinanBatas = batasUsia; mendeklarasikan variabel bertipe const int, persis tipe batasUsia, sehingga salinanBatas juga tidak boleh diubah. Aturan perbedaannya: auto menjawab “tipe apa yang pantas untuk salinan nilai ini”, sementara decltype menjawab “tipe apa yang tertulis pada entitas ini”. Pemakaian lanjutannya — misalnya menuliskan tipe kembalian fungsi — akan berguna setelah kita belajar fungsi di Section berikutnya; untuk sekarang cukup mengenali bentuknya.

auto paling bersinar ketika tipe sudah jelas dari konteks dan menulisnya hanya menambah kebisingan — pola yang akan makin sering muncul begitu kita masuk ke container pustaka standar. Namun ada satu kategori variabel yang justru kebalikannya: variabel yang nilainya tidak boleh berubah sama sekali. Untuk itulah const dan constexpr hadir, dan keduanya menjadi bahan Chapter berikutnya.

Rujukan resmi untuk topik Chapter ini: auto specifier dan decltype di cppreference.