Saya telah menggunakan auto
kata kunci baru yang tersedia di standar C ++ 11 untuk tipe templated yang rumit yang saya yakin dirancang untuk itu. Tetapi saya juga menggunakannya untuk hal-hal seperti:
auto foo = std::make_shared<Foo>();
Dan lebih skeptis untuk:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
Saya belum melihat banyak diskusi tentang topik ini. Tampaknya itu auto
bisa digunakan secara berlebihan, karena suatu jenis sering kali merupakan bentuk dokumentasi dan pemeriksaan kewarasan. Di mana Anda menarik garis dalam menggunakan auto
dan apa kasus penggunaan yang disarankan untuk fitur baru ini?
Untuk memperjelas: Saya tidak meminta pendapat filosofis; Saya meminta maksud penggunaan kata kunci ini oleh komite standar, mungkin dengan komentar tentang bagaimana penggunaan yang dimaksud diwujudkan dalam praktik.
Catatan: Pertanyaan ini dipindahkan ke SE.Programmer dan kemudian kembali ke Stack Overflow. Diskusi tentang ini dapat ditemukan dalam pertanyaan meta ini .
auto
kata kunci, maka Anda tahu bagaimana kata itu seharusnya digunakan. Itulah yang saya tanyakan, sebagai orang yang baru mengenal fitur ini, bagaimana saya harus menggunakannya?var
(yaitu, setelah orang memahami bahwa itu bukan pengetikan yang dinamis). Jika mau, Anda dapat mulai dengan pertanyaan ini dan menelusuri pertanyaan terkait.auto foo = bla();
"buruk" jelas merupakan opini, bukan fakta, yang menjadikan pertanyaan ini dan menjawab diskusi, yang membuatnya relevan bagi Programmer SE, yang persis seperti yang ditunjukkan oleh suara dekat. /Jawaban:
Saya pikir orang harus menggunakan
auto
kata kunci kapan pun sulit mengatakan bagaimana cara menulis jenisnya pada pandangan pertama, tetapi jenis sisi kanan suatu ungkapan sudah jelas. Misalnya, menggunakan:untuk mendapatkan tipe kunci komposit
boost::multi_index
, meskipun Anda tahu ituint
. Anda tidak bisa hanya menulisint
karena itu bisa diubah di masa depan. Saya akan menulisauto
dalam kasus ini.Jadi, jika
auto
kata kunci meningkatkan keterbacaan dalam kasus tertentu, maka gunakan. Anda dapat menulisauto
ketika jelas bagi pembaca jenis apa yangauto
diwakilinya.Berikut ini beberapa contohnya:
sumber
bla()
Anda kembalikanfoo
.Gunakan di
auto
mana pun Anda bisa — khususnyaconst auto
agar efek samping tidak terlalu menjadi perhatian. Anda tidak perlu khawatir tentang jenis kecuali dalam kasus yang jelas, tetapi mereka masih akan diverifikasi secara statis untuk Anda, dan Anda dapat menghindari beberapa pengulangan. Di manaauto
tidak layak, Anda dapat menggunakandecltype
untuk mengekspresikan tipe secara semantik sebagai kontrak berdasarkan ekspresi. Kode Anda akan terlihat berbeda, tetapi itu akan menjadi perubahan positif.sumber
auto&&
dalam situasi kompleks edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&
atauconst auto
kecuali saya secara eksplisit ingin bermutasi atau pindah.auto str = std::string();
bukanstd::string str;
?Mudah. Gunakan saat Anda tidak peduli apa jenisnya. Sebagai contoh
Yang saya pedulikan di sini
i
adalah apa pun yang ada di wadah.Ini agak seperti typedef.
Di sini, saya tidak peduli apakah
h
danw
mengapung atau ganda, hanya saja mereka adalah tipe apa pun yang cocok untuk mengekspresikan ketinggian dan berat .Atau pertimbangkan
Di sini semua yang saya pedulikan adalah bahwa itu iterator yang cocok, mendukung
operator++()
, itu seperti bebek mengetik dalam hal ini.Juga jenis lambda tidak bisa dieja, begitu
auto f = []...
juga gaya yang baik. Alternatifnya adalah castingstd::function
tetapi itu datang dengan overhead.Saya tidak bisa membayangkan "penyalahgunaan"
auto
. Yang paling dekat yang dapat saya bayangkan adalah merampas diri Anda dari konversi eksplisit ke beberapa tipe signifikan - tetapi Anda tidak akan menggunakannyaauto
untuk itu, Anda akan membangun objek dari tipe yang diinginkan.Jika Anda dapat menghapus beberapa redundansi dalam kode Anda tanpa memperkenalkan efek samping, maka itu harus dilakukan.
Contoh tandingan (dipinjam dari jawaban orang lain):
Di sini kita TIDAK peduli apa tipenya, jadi kita harus menulis
Someclass i;
danfor(unsigned x = y;...
sumber
auto
.Lakukan untuk itu. Gunakan di
auto
mana saja itu membuat menulis kode lebih mudah.Setiap fitur baru dalam bahasa apa pun akan digunakan secara berlebihan oleh setidaknya beberapa jenis programer. Hanya melalui moderat berlebihan oleh beberapa programmer berpengalaman (bukan noobs) bahwa sisa programmer berpengalaman mempelajari batas-batas penggunaan yang tepat. Penggunaan berlebihan yang berlebihan biasanya buruk, tetapi bisa menjadi baik karena penggunaan yang berlebihan tersebut dapat menyebabkan peningkatan fitur atau fitur yang lebih baik untuk menggantinya.
Tetapi jika saya bekerja pada kode dengan lebih dari beberapa baris seperti
di mana tipe ditunjukkan nol kali, saya mungkin ingin mengubah baris-baris itu untuk memasukkan tipe. Contoh pertama sangat bagus karena jenisnya dinyatakan sekali, dan
auto
menyelamatkan kita dari keharusan menulis jenis templated berantakan dua kali. Hore untuk C ++++. Tapi secara eksplisit menunjukkan tipe nol kali, jika itu tidak mudah terlihat di baris terdekat, membuat saya gugup, setidaknya di C ++ dan penerusnya. Untuk bahasa lain yang dirancang untuk bekerja pada tingkat yang lebih tinggi dengan lebih banyak abstraksi, polimorfisme, dan kedermawanan, tidak masalah.sumber
Di C ++ dan Beyond 2012 di panel Tanya Kami Apa Pun, ada pertukaran fantastis antara Andrei Alexandrescu, Scott Meyers dan Herb Sutter berbicara tentang kapan harus digunakan dan tidak digunakan
auto
. Lewati ke menit 25:03 untuk diskusi 4 menit. Ketiga pembicara memberikan poin yang sangat baik yang harus diingat saat tidak digunakanauto
.Saya sangat mendorong orang untuk sampai pada kesimpulan mereka sendiri, tetapi yang saya ambil adalah untuk digunakan di
auto
mana-mana kecuali :Penggunaan liberal
explicit
membantu mengurangi kekhawatiran terhadap yang terakhir, yang membantu meminimalkan jumlah waktu yang pertama adalah masalah.Mengulangi apa yang dikatakan Herb, "jika Anda tidak melakukan X, Y, dan Z, gunakan
auto
. Pelajari apa itu X, Y, dan Z dan maju dan gunakan diauto
tempat lain."sumber
Ya, itu bisa digunakan secara berlebihan sehingga merugikan keterbacaan. Saya sarankan menggunakannya dalam konteks di mana tipe yang tepat panjang, atau unutterable, atau tidak penting untuk keterbacaan, dan variabel berumur pendek. Misalnya, tipe iterator biasanya panjang dan tidak penting, jadi
auto
akan berhasil:auto
di sini tidak ada salahnya dibaca.Contoh lain adalah tipe aturan parser, yang bisa panjang dan berbelit-belit. Membandingkan:
dengan
Di sisi lain, ketika jenis diketahui dan sederhana, akan jauh lebih baik jika dinyatakan secara eksplisit:
daripada
sumber
begin()
danend()
, atau ukuran langkah Anda adalah selain dari satu, atau Anda memodifikasi wadah saat Anda mengulang, pernyataan berbasis rentang untuk pernyataan tidak akan membantu Anda.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>
apakah itu?space
, dan mencarinya. Bagaimanapun juga, itulah informasi yang lebih berguna ... masalahnya bukan "tipe apa variabel baru ini" melainkan "apaspace & space & space
artinya?" Jenis ekspresi yang sebenarnya hanyalah noise.auto
bisa sangat berbahaya dalam kombinasi dengan templat ekspresi yang banyak digunakan oleh pustaka aljabar linier seperti Eigen atau OpenCV.Bug yang disebabkan oleh kesalahan jenis ini sangat menyebalkan. Salah satu solusi yang mungkin adalah dengan melemparkan hasil secara eksplisit ke tipe yang diharapkan jika Anda benar-benar menggunakan auto untuk gaya deklarasi kiri-ke-kanan.
sumber
A*B
ekspresi disalin dalamauto
variabel atau sesuatu yang lain, perilaku yang Anda gambarkan masih ada.auto
.diag(A * B)
tidak harus membuang siklus menghitung elemen-elemen off-diagonal.Saya menggunakan
auto
batasan wihout dan tidak menghadapi masalah. Saya bahkan kadang-kadang akhirnya menggunakannya untuk tipe sederhana sepertiint
. Ini membuat c ++ bahasa tingkat yang lebih tinggi bagi saya, dan memungkinkan untuk mendeklarasikan variabel dalam c ++ seperti pada python. Setelah menulis kode python, saya bahkan terkadang menulis misdari pada
Ini adalah satu kasus di mana saya akan mengatakan itu adalah penyalahgunaan
auto
kata kunci.Seringkali saya tidak keberatan apa jenis objek yang tepat, saya lebih tertarik pada fonctionality-nya, dan sebagai nama fungsi umumnya mengatakan sesuatu tentang objek yang mereka kembalikan,
auto
tidak ada salahnya: misalnyaauto s = mycollection.size()
, saya dapat menebak bahwas
akan menjadi semacam integer, dan dalam kasus yang jarang terjadi di mana saya peduli tentang jenis yang tepat, mari kita periksa prototipe fungsi lalu (maksud saya, saya lebih suka harus memeriksa ketika saya membutuhkan info, daripada apriori ketika kode ditulis, hanya kalau-kalau itu akan berguna suatu hari nanti, seperti dalamint_type s = mycollection.size()
).Mengenai contoh ini dari jawaban yang diterima:
Dalam kode saya, saya masih menggunakan
auto
dalam kasus ini, dan jika saya inginx
tidak ditandatangani, maka saya menggunakan fungsi utilitas, bernama saymake_unsigned
, yang menyatakan dengan jelas keprihatinan saya:disclaimer: Saya hanya menjelaskan penggunaan saya , saya tidak kompeten untuk memberikan saran!
sumber
auto i = MyClass()
.as_unsigned
direkomendasikan di sana, atau bahkanauto w = widget{};
.Salah satu masalah utama dengan program C ++ adalah memungkinkan Anda untuk menggunakan variabel yang tidak diinisialisasi . Ini membawa kita pada perilaku program yang tidak deterministik. Perlu dicatat bahwa kompiler modern sekarang melempar pesan peringatan yang sesuai / pesan jika program ingin menggunakannya.
Hanya untuk menggambarkan ini, pertimbangkan di bawah ini program c ++:
Jika saya mengkompilasi program ini menggunakan modern compiler (GCC), itu memberi peringatan. Peringatan semacam itu mungkin tidak terlalu jelas jika kita bekerja dengan kode produksi nyata yang kompleks.
================================================== =============================== Sekarang jika kita mengubah program kita yang menggunakan otomatis , maka kompilasi kita mendapatkan yang berikut:
Dengan otomatis, tidak mungkin menggunakan variabel yang tidak diinisialisasi. Ini adalah keuntungan besar yang mungkin kita dapatkan (gratis), jika kita mulai menggunakan otomatis .
Konsep ini dan konsep C ++ modern hebat lainnya dijelaskan oleh pakar C ++, Herb Shutter dalam ceramah CppCon14- nya :
Kembali ke Dasar! Hal-hal penting dari Gaya C ++ Modern
sumber
auto
.auto
- tetapi Anda tidak perlu untuk menghindari masalah ini.Satu bahaya yang saya perhatikan adalah dalam hal referensi. misalnya
Masalahnya adalah another_ref sebenarnya bukan referensi dalam hal ini adalah MyBigObject bukan MyBigObject &. Anda akhirnya menyalin objek besar tanpa menyadarinya.
Jika Anda mendapatkan referensi langsung dari suatu metode, Anda mungkin tidak berpikir tentang apa itu sebenarnya.
Anda memerlukan "otomatis &" atau "otomatis & &"
sumber
Gunakan
auto
jika masuk akal untuk jenis yang akan disimpulkan. Jika Anda memiliki sesuatu yang Anda tahu bilangan bulat, atau Anda tahu itu adalah string, cukup gunakan int / std :: string, dll. Saya tidak akan khawatir tentang "terlalu banyak menggunakan" fitur bahasa kecuali jika sampai pada titik konyolnya, atau mengaburkan kode.Itu pendapat saya.
sumber
auto
kata kunci hanya dapat digunakan untuk variabel lokal, bukan untuk argumen atau anggota kelas / struct. Jadi, aman dan layak untuk menggunakannya di mana pun Anda suka. Saya sering menggunakannya. Jenis ini dideduksi pada waktu kompilasi, debugger menunjukkan jenisnya saat debugging,sizeof
melaporkannya dengan benar,decltype
akan memberikan jenis yang benar - tidak ada salahnya. Saya tidak dihitungauto
sebagai terlalu sering digunakan!sumber
TL; DR: Lihat aturan praktis di bagian bawah.
The jawaban yang diterima menunjukkan aturan berikut praktis:
Tapi saya akan mengatakan itu terlalu ketat. Kadang-kadang saya tidak peduli dengan jenisnya, karena pernyataan itu cukup informatif tanpa saya repot meluangkan waktu untuk mencari tahu jenisnya. Apa yang saya maksud dengan itu? Perhatikan contoh yang muncul di beberapa jawaban:
Apa yang menjadikan ini contoh penyalahgunaan
auto
? Apakah ini ketidaktahuan saya tentangf()
tipe pengembalian? Yah, memang mungkin bisa membantu jika saya mengetahuinya, tapi - itu bukan perhatian utama saya. Apa yang lebih dari masalah adalah itux
danf()
sangat tidak berarti. Jika kita punya:sebagai gantinya, maka saya biasanya tidak peduli apakah tipe kembalinya fungsi itu jelas atau tidak. Membaca pernyataan itu, saya tahu apa yang saya lakukan dan saya cukup tahu tentang apa yang semantik nilai balik tidak merasa saya perlu juga tahu jenisnya.
Jadi jawaban saya adalah: Gunakan
auto
kapan pun kompiler mengizinkannya, kecuali:Dan juga:
auto
dengan tipe konkret.sumber
Salah satu pengalaman pahit saya
auto
adalah menggunakannya dengan ekspresi lambda :Sebenarnya, di sini
i
diselesaikan untuk fungsi pointerint(*)()
. Ini hanya sederhanacout
, tetapi bayangkan seperti apa kesalahan kompilasi / runtime buruk yang dapat menyebabkannya ketika digunakantemplate
.Anda harus menghindari
auto
dengan ekspresi seperti itu dan memasukkanreturn
tipe yang tepat (atau dikendalikandecltype()
)Penggunaan yang benar untuk contoh di atas adalah,
sumber
()
pada akhirnya. Lambdas ada untuk bertindak sebagai fungsi dan dari situlah konversi pointer fungsi berasal. Jika Anda ingin langsung menyebutnya, mengapa menggunakan lambda?auto i = 0;
bekerja dengan baik.auto x = []() { /* .... whatever goes in here ... */ }()
lebih baik daripadaauto x = /* .... whatever goes in here ... */;
, yaitu hal yang sama, tanpa lambda? Saya menemukan itu agak sia-sia, karena alasan yang samaauto x = 42 + y - 42
tidak ada gunanya.