Hingga tahun 2011, C++ praktis berhenti di standar C++03 yang masih menuntut gaya menulis panjang: tipe diulang dua kali, pengelolaan memori new/delete dilakukan manual, dan banyak fitur hanya bisa dicapai lewat trik pustaka yang rumit. Standar C++11 mengubah segalanya; komunitas menyebut periode setelahnya sebagai modern C++ era, karena C++11 memperkenalkan hampir seluruh fondasi yang kita pakai sampai sekarang. Beberapa fitur terbesarnya: auto untuk menyimpulkan tipe, range-based for untuk mengiterasi tanpa indeks, lambda untuk fungsi kecil di tempat, smart pointer untuk kepemilikan memori otomatis, move semantics untuk memindah sumber daya alih-alih menyalin, nullptr yang tegas, uniform initialization dengan {}, dan constexpr untuk perhitungan saat kompilasi. Bab-bab setelah chapter ini akan membedah masing-masing secara mendalam; di sini kita melihat semuanya bekerja dalam satu program agar terasa seberapa besar perubahannya.
Program yang Menggabungkan Fitur C++11 #
Program berikut dikompilasi murni dengan -std=c++11 — tidak ada fitur standar yang lebih baru — dan setiap blok fitur sengaja dibuat sesingkat mungkin.
// panorama-cpp11.cpp — sekali pandang: fitur C++11 yang mengubah cara menulis C++
// Kompilasi: g++ -std=c++11 -Wall -Wextra panorama-cpp11.cpp -o panorama
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
// constexpr (C++11): fungsi yang bisa dihitung saat kompilasi
constexpr int kuadrat(int x) {
return x * x;
}
// move semantics (C++11): constructor pindah berpindah memori, bukan menyalin
struct Transaksi {
std::string keterangan;
int nominal;
Transaksi(std::string k, int n) : keterangan(std::move(k)), nominal(n) {
std::cout << " buat : " << keterangan << "\n";
}
Transaksi(Transaksi&& lain) noexcept
: keterangan(std::move(lain.keterangan)), nominal(lain.nominal) {
std::cout << " pindah: " << keterangan << "\n";
}
};
int main() {
std::cout << "kuadrat(9) saat kompilasi: " << kuadrat(9) << "\n";
auto kata = std::string("modern"); // auto: tipe disimpulkan compiler
std::cout << "auto: " << kata << "\n";
std::vector<int> skor = {10, 20, 30}; // uniform initialization
for (int s : skor) { // range-based for
std::cout << s << " ";
}
std::cout << "\n";
std::unique_ptr<int> p(new int(42)); // smart pointer (C++11)
std::cout << "unique_ptr: " << *p << "\n";
p.reset(); // tidak perlu delete manual
std::cout << "setelah reset, p adalah ";
if (p == nullptr) { // nullptr (C++11)
std::cout << "nullptr\n";
}
auto gandakan = [](int x) { return x * 2; }; // lambda (C++11)
std::cout << "lambda gandakan(21): " << gandakan(21) << "\n";
std::vector<Transaksi> log;
log.reserve(2);
log.emplace_back("kopi", 18000); // konstruksi langsung di container
log.emplace_back("roti", 9000);
std::cout << "isi log: ";
for (const auto& t : log) {
std::cout << t.keterangan << "; ";
}
std::cout << "\n";
return 0;
}Output yang Dihasilkan:
kuadrat(9) saat kompilasi: 81
auto: modern
10 20 30
unique_ptr: 42
setelah reset, p adalah nullptr
lambda gandakan(21): 42
buat : kopi
buat : roti
isi log: kopi; roti; Mari kita bedah fitur demi fitur:
- Baris 11-13 (
constexpr int kuadrat): C++11 memberi fungsi izin dihitung saat kompilasi bila argumennya konstanta.kuadrat(9)berubah menjadi81oleh compiler, tanpa instruksi pemanggilan fungsi di binary. - Baris 32 (
auto kata): compiler menyimpulkan tipe dari inisialisasi, jadistd::stringcukup ditulis sekali. Ini bukan tipe dinamis — tipe tetap diputuskan saat kompilasi. - Baris 35-38 (uniform init + range-for): daftar
{10, 20, 30}mengisi vector tanpapush_backberulang, dan range-based for berjalan tanpa indeks, tanpabegin()/end()eksplisit, tanpa risiko salah batas. - Baris 41-47 (smart pointer + nullptr):
std::unique_ptrmembebaskan memori lewat destructor ketika keluar scope — kita tidak menulisdeletesama sekali.nullptrmenggantikanNULLdan tidak lagi memicu overload ambiguity ketika dilewatkan ke fungsi bertipe pointer atau integer. - Baris 49-50 (lambda): fungsi kecil didefinisikan langsung di tempat pemakaian. Tanpa lambda, kita harus menulis function terpisah atau membuat struct dengan
operator()— kode tersebar dari tempat logikanya. - Baris 20-26 + 54-55 (move semantics + emplace):
emplace_backmembangunTransaksilangsung di dalam vector; trace output menunjukkan hanyabuat— tidak ada constructor salin. Constructor pindah (Baris 23-26) akan muncul ketika vector diperbesar, memindahkan string alih-alih menyalinnya.
Sebelum dan Sesudah C++11 #
Perbedaannya paling terasa ketika kode lama dan baru diletakkan bersebelahan. Task “menjumlahkan semua elemen vector dan mencarinya” di C++03 memerlukan indeks, iterator eksplisit, dan tipe yang ditulis penuh:
// Gaya C++03
std::vector<std::string>::iterator it;
for (it = v.begin(); it != v.end(); ++it) {
if (*it == "kunci") break;
}
// Gaya C++11
for (const auto& item : v) {
if (item == "kunci") break;
}Untuk kepemilikan memori dinamis, C++03 mendorong pola T* p = new T; yang mudah bocor ketika ada return di tengah jalan atau exception terlempar. C++11 menjawabnya dengan std::unique_ptr dan std::shared_ptr: kepemilikan jelas, pelepasan otomatis, dan aturan rule of zero bisa diterapkan. Penjumlahan variadic di C++03 membutuhkan rekursi template bertingkat; C++11 memberi variadic templates yang kemudian dimatangkan C++17 menjadi fold expression. Tidak satu pun fitur lama hilang — semua kode C++03 tetap jalan — tetapi gaya idiomatik bergeser total.
Mengapa Disebut Era Modern #
C++11 bukan sekadar tambalan fitur; ia mengubah filosofi bahasa menjadi abstraction without regret — abstraksi tinggi tanpa penalti performa. Lambda dan range-based for membuat kode deklaratif; smart pointer membuat keamanan memori jadi bawaan; move semantics membuat pengembalian container besar murah sehingga gaya fungsional yang mengembalikan nilai tidak lagi mahal. Di atas itu, constexpr dan static assertion memindahkan pemeriksaan dari runtime ke waktu kompilasi.
Standar berikutnya (C++14, C++17, C++20, C++23) hampir semuanya memoles atau memperluas fondasi C++11 — generic lambda memperluas lambda, structured bindings memperluas auto, concepts memperluas template, coroutine memperluas function. Karena itu memahami C++11 dengan baik membuat semua standar berikutnya terasa alami. Kita mulai dari perbaikan halus C++14 di chapter berikutnya.
Rujukan resmi: cppreference — sejarah fitur C++11 , cppreference — auto .