Saya kira ini agak subyektif; Saya tidak yakin apakah pendapatnya akan bulat (saya telah melihat banyak cuplikan kode tempat referensi dikembalikan).
Menurut komentar terhadap pertanyaan ini, saya baru saja bertanya, mengenai inisialisasi referensi , mengembalikan referensi bisa jahat karena, [seperti yang saya mengerti] membuatnya lebih mudah untuk tidak menghapusnya, yang dapat menyebabkan kebocoran memori.
Ini membuat saya khawatir, karena saya telah mengikuti contoh (kecuali saya membayangkan hal-hal) dan melakukan ini di beberapa tempat yang adil ... Apakah saya salah paham? Apakah itu jahat? Kalau begitu, seberapa jahatkah?
Saya merasa bahwa karena kantong campuran pointer dan referensi saya, dikombinasikan dengan fakta bahwa saya baru menggunakan C ++, dan kebingungan total tentang apa yang harus digunakan ketika, aplikasi saya pasti kehabisan memori ...
Juga, saya mengerti bahwa menggunakan pointer pintar / bersama umumnya diterima sebagai cara terbaik untuk menghindari kebocoran memori.
Jawaban:
Secara umum, mengembalikan referensi sangat normal dan terjadi setiap saat.
Jika yang kamu maksud:
Itu semua jenis kejahatan. Tumpukan yang dialokasikan
i
akan hilang dan Anda tidak merujuk apa pun. Ini juga jahat:Karena sekarang klien pada akhirnya harus melakukan yang aneh:
Perhatikan bahwa referensi nilai masih hanya referensi, jadi semua aplikasi jahat tetap sama.
Jika Anda ingin mengalokasikan sesuatu yang hidup di luar cakupan fungsi, gunakan pointer pintar (atau secara umum, wadah):
Dan sekarang klien menyimpan pointer pintar:
Referensi juga boleh digunakan untuk mengakses hal-hal yang Anda tahu seumur hidup tetap terbuka pada tingkat yang lebih tinggi, misalnya:
Di sini kita tahu tidak apa-apa untuk mengembalikan referensi
i_
karena apa pun yang memanggil kita mengelola masa instance kelas, jadii_
akan hidup setidaknya selama itu.Dan tentu saja, tidak ada yang salah dengan hanya:
Jika seumur hidup harus diserahkan kepada penelepon, dan Anda hanya menghitung nilainya.
Ringkasan: tidak apa-apa untuk mengembalikan referensi jika umur objek tidak akan berakhir setelah panggilan.
sumber
return new int
.Tidak. Tidak, tidak, seribu kali tidak.
Apa yang jahat adalah membuat referensi ke objek yang dialokasikan secara dinamis dan kehilangan pointer asli. Ketika Anda
new
sebuah objek Anda mengasumsikan kewajiban untuk memiliki jaminandelete
.Tetapi lihat, misalnya
operator<<
: yang harus mengembalikan referensi, atautidak akan bekerja
sumber
Anda harus mengembalikan referensi ke objek yang ada yang tidak segera pergi, dan di mana Anda tidak bermaksud melakukan transfer kepemilikan.
Jangan pernah mengembalikan referensi ke variabel lokal atau semacamnya, karena itu tidak akan ada untuk dirujuk.
Anda dapat mengembalikan referensi ke sesuatu yang terpisah dari fungsi, yang tidak Anda harapkan fungsi pemanggilannya bertanggung jawab untuk dihapus. Ini adalah kasus untuk tipikal
operator[]
fungsi .Jika Anda membuat sesuatu, Anda harus mengembalikan nilai atau penunjuk (biasa atau pintar). Anda dapat mengembalikan nilai secara bebas, karena akan menjadi variabel atau ekspresi dalam fungsi panggilan. Jangan pernah mengembalikan pointer ke variabel lokal, karena itu akan hilang.
sumber
Saya menemukan jawabannya tidak memuaskan jadi saya akan menambahkan dua sen saya.
Mari kita menganalisis kasus-kasus berikut:
Penggunaan yang salah
Ini jelas kesalahan
Penggunaan dengan variabel statis
Ini benar, karena variabel statis ada sepanjang masa program.
Ini juga cukup umum ketika menerapkan pola Singleton
Pemakaian:
Operator
Kontainer perpustakaan standar sangat bergantung pada penggunaan operator yang mengembalikan referensi, misalnya
dapat digunakan sebagai berikut
Akses cepat ke data internal
Ada saat-saat & dapat digunakan untuk akses cepat ke data internal
dengan penggunaan:
NAMUN, ini dapat menyebabkan jebakan seperti ini:
sumber
true
:If((a*b) == (c*d))
Container::data()
Implementasi harus membacareturn m_data;
Itu tidak jahat. Seperti banyak hal dalam C ++, ada baiknya jika digunakan dengan benar, tetapi ada banyak jebakan yang harus Anda perhatikan saat menggunakannya (seperti mengembalikan referensi ke variabel lokal).
Ada hal-hal baik yang dapat dicapai dengannya (seperti peta [nama] = "halo dunia")
sumber
map[name] = "hello world"
?HashMap<String,Integer>
dalam Java? : PTidak benar. Mengembalikan referensi tidak menyiratkan kepemilikan semantik. Yaitu, hanya karena Anda melakukan ini:
... tidak berarti Anda sekarang memiliki memori yang disebut oleh v;
Namun, ini adalah kode yang mengerikan:
Jika Anda melakukan sesuatu seperti ini karena "Anda tidak memerlukan pointer pada contoh itu" maka: 1) cukup referensi pointer jika Anda memerlukan referensi, dan 2) Anda akhirnya akan membutuhkan pointer, karena Anda harus mencocokkan baru dengan delete, dan Anda perlu pointer untuk memanggil delete.
sumber
Ada dua kasus:
referensi const - ide bagus, kadang-kadang, terutama untuk objek berat atau kelas proxy, pengoptimalan kompiler
referensi non-const --bad ide, kadang-kadang, istirahat enkapsulasi
Keduanya berbagi masalah yang sama - berpotensi menunjuk ke objek yang hancur ...
Saya akan merekomendasikan menggunakan smart pointer untuk banyak situasi di mana Anda harus mengembalikan referensi / pointer.
Perhatikan juga hal-hal berikut:
Ada aturan formal - Standar C ++ (bagian 13.3.3.1.4 jika Anda tertarik) menyatakan bahwa sementara hanya dapat terikat ke referensi const - jika Anda mencoba menggunakan referensi non-const, kompiler harus menandai ini sebagai kesalahan.
sumber
Bukan saja itu bukan kejahatan, terkadang juga penting. Sebagai contoh, akan mustahil untuk mengimplementasikan operator [] std :: vector tanpa menggunakan nilai balik referensi.
sumber
operator[]
untuk wadah tanpa menggunakan referensi ... danstd::vector<bool>
tidak. (Dan menciptakan kekacauan nyata dalam prosesnya)::std::vector<bool>
yang telah Anda sebutkan).std::vector<T>
kode templat rusak, jikaT
mungkinbool
, karenastd::vector<bool>
memiliki perilaku yang sangat berbeda dari instansi lain. Ini berguna, tetapi seharusnya diberi nama sendiri dan bukan spesialisasistd::vector
.Tambahan untuk jawaban yang diterima:
Saya berpendapat bahwa contoh ini tidak baik dan harus dihindari jika memungkinkan. Mengapa? Sangat mudah untuk berakhir dengan referensi yang menggantung .
Untuk mengilustrasikan poin dengan contoh:
memasuki zona bahaya:
sumber
referensi pengembalian biasanya digunakan dalam overloading operator di C ++ untuk Objek besar, karena mengembalikan nilai perlu operasi penyalinan (dalam overloading perator, kami biasanya tidak menggunakan pointer sebagai nilai balik)
Tetapi pengembalian referensi dapat menyebabkan masalah alokasi memori. Karena referensi ke hasil akan dikeluarkan dari fungsi sebagai referensi ke nilai kembali, nilai kembali tidak bisa menjadi variabel otomatis.
jika Anda ingin menggunakan referensi yang kembali, Anda dapat menggunakan buffer objek statis. sebagai contoh
dengan cara ini, Anda dapat menggunakan referensi pengembalian dengan aman.
Tapi Anda selalu bisa menggunakan pointer daripada referensi untuk mengembalikan nilai di functiong.
sumber
saya pikir menggunakan referensi sebagai nilai kembali fungsi jauh lebih lurus daripada menggunakan pointer sebagai nilai balik fungsi. Kedua Akan selalu aman untuk menggunakan variabel statis yang merujuk nilai kembali.
sumber
Hal terbaik adalah membuat objek dan meneruskannya sebagai parameter referensi / penunjuk ke fungsi yang mengalokasikan variabel ini.
Mengalokasikan objek dalam fungsi dan mengembalikannya sebagai referensi atau pointer (pointer lebih aman namun) adalah ide yang buruk karena membebaskan memori di akhir blok fungsi.
sumber
Fungsi getPtr dapat mengakses memori dinamis setelah penghapusan atau bahkan objek null. Yang dapat menyebabkan Pengecualian Akses Buruk. Sebaliknya pengambil dan penyetel harus diimplementasikan dan ukuran diverifikasi sebelum kembali.
sumber
Berfungsi sebagai lvalue (alias, pengembalian referensi non-const) harus dihapus dari C ++. Ini sangat tidak intuitif. Scott Meyers ingin min () dengan perilaku ini.
yang tidak benar-benar perbaikan
Yang terakhir bahkan lebih masuk akal.
Saya menyadari bahwa fungsi sebagai lvalue penting untuk aliran gaya C ++, tetapi perlu menunjukkan bahwa aliran gaya C ++ mengerikan. Saya bukan satu-satunya yang berpikir ini ... seingat saya, Alexandrescu memiliki artikel besar tentang bagaimana melakukan yang lebih baik, dan saya percaya dorongan juga telah mencoba untuk menciptakan metode I / O aman jenis yang lebih baik.
sumber
vector::operator[]
sebagai contoh. Apakah Anda lebih suka menulisv.setAt(i, x)
atauv[i] = x
? Yang terakhir adalah JAUH superior.v.setAt(i, x)
kapan saja. Jauh lebih unggul.Saya mengalami masalah nyata di mana itu memang jahat. Pada dasarnya seorang pengembang mengembalikan referensi ke objek dalam vektor. Itu buruk!!!
Rincian lengkap yang saya tulis di Janurary: http://developer-resource.blogspot.com/2009/01/pros-and-cons-of-returing-references.html
sumber
Tentang kode mengerikan:
Jadi, memang, penunjuk memori hilang setelah kembali. Tetapi jika Anda menggunakan shared_ptr seperti itu:
Memori tidak hilang setelah kembali dan akan dibebaskan setelah penugasan.
sumber