Stroustrup membuat beberapa komentar bagus tentang ini di konferensi Going Native 2013.
Lewati saja sekitar 25m50s dalam video ini . (Saya sarankan menonton seluruh video sebenarnya, tetapi ini melompati hal-hal tentang pengumpulan sampah.)
Ketika Anda memiliki bahasa yang benar-benar hebat yang membuatnya mudah (dan aman, dapat diprediksi, dan mudah dibaca, dan mudah diajari) untuk berurusan dengan objek dan nilai secara langsung, menghindari (eksplisit) penggunaan tumpukan, maka Anda bahkan tidak ingin pengumpulan sampah.
Dengan C ++ modern, dan barang-barang yang kami miliki di C ++ 11, pengumpulan sampah tidak lagi diinginkan kecuali dalam keadaan terbatas. Bahkan, bahkan jika pengumpul sampah yang baik dibangun ke dalam salah satu kompiler C ++ utama, saya pikir itu tidak akan sering digunakan. Akan lebih mudah , tidak sulit, untuk menghindari GC.
Dia menunjukkan contoh ini:
void f(int n, int x) {
Gadget *p = new Gadget{n};
if(x<100) throw SomeException{};
if(x<200) return;
delete p;
}
Ini tidak aman di C ++. Tetapi juga tidak aman di Jawa! Dalam C ++, jika fungsi kembali lebih awal, delete
tidak akan pernah dipanggil. Tetapi jika Anda memiliki pengumpulan sampah penuh, seperti di Jawa, Anda hanya mendapatkan saran bahwa objek tersebut akan dihancurkan "di beberapa titik di masa depan" ( Pembaruan: bahkan lebih buruk dari ini. Java tidakberjanji untuk memanggil finalizer - itu mungkin tidak pernah disebut). Ini tidak cukup baik jika Gadget memegang pegangan file terbuka, atau koneksi ke database, atau data yang telah Anda buffer untuk menulis ke database di kemudian hari. Kami ingin Gadget dimusnahkan segera setelah selesai, untuk membebaskan sumber daya ini sesegera mungkin. Anda tidak ingin server database Anda berjuang dengan ribuan koneksi database yang tidak lagi diperlukan - ia tidak tahu bahwa program Anda selesai berfungsi.
Jadi apa solusinya? Ada beberapa pendekatan. Pendekatan yang jelas, yang akan Anda gunakan untuk sebagian besar objek Anda adalah:
void f(int n, int x) {
Gadget p = {n}; // Just leave it on the stack (where it belongs!)
if(x<100) throw SomeException{};
if(x<200) return;
}
Ini membutuhkan lebih sedikit karakter untuk diketik. Tidak ada new
yang menghalangi. Anda tidak perlu mengetik Gadget
dua kali. Objek dihancurkan di akhir fungsi. Jika ini yang Anda inginkan, ini sangat intuitif. Gadget
Berperilaku sama dengan int
atau double
. Mudah ditebak, mudah dibaca, mudah diajarkan. Semuanya adalah 'nilai'. Terkadang nilai yang besar, tetapi nilai lebih mudah untuk diajarkan karena Anda tidak memiliki 'tindakan di kejauhan' yang Anda dapatkan dengan pointer (atau referensi).
Sebagian besar objek yang Anda buat hanya untuk digunakan dalam fungsi yang membuatnya, dan mungkin diteruskan sebagai input ke fungsi anak. Pemrogram tidak harus berpikir tentang 'manajemen memori' ketika mengembalikan objek, atau berbagi objek di seluruh bagian perangkat lunak yang terpisah.
Lingkup dan umur adalah penting. Sebagian besar waktu, lebih mudah jika seumur hidup sama dengan ruang lingkup. Lebih mudah dimengerti dan lebih mudah untuk diajar. Ketika Anda menginginkan masa hidup yang berbeda, harus jelas membaca kode yang Anda lakukan ini, dengan menggunakanshared_ptr
misalnya. (Atau mengembalikan objek (besar) dengan nilai, meningkatkan gerakan-semantik atau unique_ptr
.
Ini mungkin tampak seperti masalah efisiensi. Bagaimana jika saya ingin mengembalikan Gadget foo()
? Semantik bergerak C ++ 11 membuatnya lebih mudah untuk mengembalikan objek besar. Cukup tulisGadget foo() { ... }
dan itu hanya akan bekerja, dan bekerja dengan cepat. Anda tidak perlu mengacaukan &&
diri sendiri, kembalikan saja dengan nilai dan bahasa akan sering dapat melakukan optimasi yang diperlukan. (Bahkan sebelum C ++ 03, kompiler melakukan pekerjaan yang sangat baik untuk menghindari penyalinan yang tidak perlu.)
Seperti yang dikatakan Stroustrup di bagian lain dalam video (parafrase): "Hanya seorang ilmuwan komputer yang bersikeras menyalin objek, dan kemudian menghancurkan yang asli. (Hadirin tertawa). Mengapa tidak hanya memindahkan objek secara langsung ke lokasi baru? Inilah yang dilakukan manusia (bukan ilmuwan komputer) harapkan. "
Ketika Anda dapat menjamin hanya satu salinan dari suatu objek yang dibutuhkan, akan lebih mudah untuk memahami umur dari objek tersebut. Anda dapat memilih kebijakan seumur hidup yang Anda inginkan, dan pengumpulan sampah ada jika Anda mau. Tetapi ketika Anda memahami manfaat dari pendekatan lain, Anda akan menemukan bahwa pengumpulan sampah ada di bagian bawah daftar preferensi Anda.
Jika itu tidak berhasil untuk Anda, Anda dapat menggunakan unique_ptr
, atau gagal shared_ptr
,. C ++ 11 yang ditulis dengan baik lebih pendek, lebih mudah dibaca, dan lebih mudah diajarkan daripada banyak bahasa lain dalam hal manajemen memori.