Setiap pemanggilan fungsi menimbulkan biaya kecil: CPU menyimpan posisi kembali, menyiapkan argumen, melompat ke badan fungsi, lalu melompat balik. Untuk fungsi yang isinya dua baris dan dipanggil jutaan kali dalam loop, biaya seremoni itu bisa melampaui pekerjaan sebenarnya. Kata kunci inline adalah jawaban C++ atas persoalan ini: saran kepada compiler agar badan fungsi ditempelkan langsung di titik pemanggilan. Pada Chapter ini kita menulis fungsi inline, membandingkannya dengan makro #define yang wujudnya mirip tetapi perilakunya berbahaya, lalu melihat peran ganda inline di header.
inline: Saran untuk Compiler #
Menulis fungsi inline tidak mengubah cara memanggilnya sama sekali — hanya deklarasinya yang diberi kata kunci. Program berikut memakai inline int kuadrat dan sengaja menguji pemanggilan dengan efek samping n++:
#include <iostream>
inline int kuadrat(int x) {
return x * x;
}
int main() {
int n = 5;
std::cout << "kuadrat(5) : " << kuadrat(5) << "\n";
std::cout << "kuadrat(n) : " << kuadrat(n) << "\n";
// Pemanggilan dengan efek samping tetap benar pada fungsi
int hasil = kuadrat(n++);
std::cout << "kuadrat(n++) : " << hasil
<< ", n sekarang " << n << "\n";
return 0;
}Output yang Dihasilkan:
kuadrat(5) : 25
kuadrat(n) : 25
kuadrat(n++) : 25, n sekarang 6Perilakunya persis fungsi biasa — karena semantiknya memang fungsi biasa. Baris int hasil = kuadrat(n++) dievaluasi dengan urutan yang jelas: argumen n++ menghasilkan 5 untuk fungsi, n naik menjadi 6, fungsi mengembalikan 25. Perilaku yang terdefinisi rapi ini akan menjadi kontras penting saat kita melihat makronya.
Satu pemahaman yang perlu diluruskan sejak awal: inline adalah SARAN, bukan perintah. Compiler modern menilai sendiri fungsi mana yang layak ditempel — berdasarkan ukuran badan, frekuensi panggilan, dan hasil analisis optimasi — dan boleh meng-inline fungsi tanpa kata kunci sekalipun (saat flag optimasi seperti -O2 aktif), atau mengabaikan kata kunci pada fungsi raksasa. Ditambah lagi, pemanggilan fungsi kecil sering kali lebih cepat daripada perkiraan kita karena CPU modern pandai memprediksi lompatan. Jadi tulis inline sebagai niat, lalu biarkan compiler yang memutuskan.
Makro define: Kembar yang Berbahaya #
Preprocessor menyediakan cara lain yang tampak setara: makro objek/ekspresi lewat #define. Keduanya “menghilangkan pemanggilan fungsi”, tetapi cara kerjanya sama sekali berbeda — makro bekerja dengan penggantian teks mentah sebelum compiler membaca kode, tanpa tipe, tanpa evaluasi argumen yang rapi. Dua bahaya klasiknya bisa kita lihat langsung:
#define KUADRAT(x) x * x
int hasil = KUADRAT(2 + 3);
// Penggantian teks menghasilkan ekspresi: 2 + 3 * 2 + 3
// Hasilnya 11 — bukan 25 seperti yang diharapkan
Makro tidak menghitung 2 + 3 dulu; ia menempelkan teks 2 + 3 ke dalam x * x apa adanya, sehingga prioritas operator membalikkan maksud pemanggil. Perbaikan klasiknya adalah mengurung segalanya — #define KUADRAT(x) ((x) * (x)) — tetapi itu pun belum menutup satu celah lagi:
#define KUADRAT(x) ((x) * (x))
int n = 5;
int hasil = KUADRAT(n++);
// Penggantian teks menghasilkan ekspresi: ((n++) * (n++))
// n dinaikkan DUA KALI dalam satu ekspresi -> undefined behavior
Bahkan makro yang dikurung sempurna tetap menyalin teks argumen, sehingga n++ muncul dua kali dalam satu ekspresi dan n dimodifikasi dua kali tanpa urutan yang terdefinisi — kategori undefined behavior yang kita hindari sejak awal course ini. Fungsi bebas dari keduanya: argumen fungsi dievaluasi SEKALI sebelum badan berjalan, tipenya diperiksa compiler, dan KUADRAT versi makro tidak punya jaminan apa pun dari keduanya.
inline di Header #
inline menyimpan peran kedua yang kurang terkenal tetapi penting: melonggarkan aturan satu definisi (ODR) untuk fungsi. Fungsi biasa boleh didefinisikan hanya di SATU file; fungsi inline boleh didefinisikan di BANYAK file, asalkan definisinya identik. Syarat inilah yang membuat fungsi kecil di header layak ditulis lengkap — setiap file .cpp yang meng-include header itu “mendefinisikan” fungsi yang sama secara sah:
#ifndef MATEMATIKA_INLINE_H
#define MATEMATIKA_INLINE_H
// inline membolehkan definisi fungsi berada di header
inline int kaliDua(int x) {
return 2 * x;
}
#endifTanpa inline, header seperti ini akan membuat proyek multi-file gagal di tahap linking dengan multiple definition — galat yang akan kita jumpai saat menyusun proyek nyata pada Section Build System dan Project Structure. Dengan inline, linker menyatukan semua definisi identik menjadi satu. Perlu diingat, peran ini murni soal aturan bahasa: fungsi di header ber-inline belum tentu ditempelkan di titik panggil — dua makna kata yang sama tetapi tugasnya berbeda.
Rujukan resmi: cppreference: inline specifier dan GCC docs tentang inline . Dari fungsi yang memanggil dirinya di Chapter berikutnya kita akan melihat sisi lain keindahan fungsi: rekursi.