C ++ otomatis & vs otomatis

91

Saat membuat variabel lokal, apakah benar digunakan (const) auto&atau auto?

misalnya:

SomeClass object;
const auto result = object.SomeMethod();

atau const auto& result = object.SomeMethod();

Di mana SomeMethod () mengembalikan nilai non-primitif - mungkin tipe lain yang ditentukan pengguna. Pemahaman saya const auto& resultadalah benar karena hasil yang dikembalikan oleh SomeMethod () akan memanggil konstruktor salinan untuk jenis yang dikembalikan. Tolong koreksi saya jika saya salah.

Bagaimana dengan tipe primitif? Saya anggap const auto sum = 1 + 2;benar.

Apakah ini juga berlaku untuk loop berdasarkan loop?

for(const auto& object : objects)
rohunb
sumber
1
Saya sangat menyarankan Anda untuk membaca ini: safaribooksonline.com/library/view/effective-modern-c/… Dua bab pertama gratis dan menjelaskan pengurangan jenis template, yang pada dasarnya adalah cara autokerjanya (kecuali untuk kasus khusus initializer_lists, yaitu non-deduced dalam konteks template), lalu autoketik deduction.
vsoftco

Jawaban:

107

autodan auto &&mencakup sebagian besar kasus:

  • Gunakan autosaat Anda membutuhkan salinan lokal. Ini tidak akan pernah menghasilkan referensi. Konstruktor salin (atau pindahkan) harus ada, tetapi mungkin tidak dipanggil, karena pengoptimalan penghapusan salinan .

  • Gunakan auto &&saat Anda tidak peduli apakah benda tersebut lokal atau bukan. Secara teknis, ini akan selalu menghasilkan referensi, tetapi jika penginisialisasinya bersifat sementara (mis., Fungsi dikembalikan berdasarkan nilai), pada dasarnya akan berperilaku seperti objek lokal Anda sendiri.

    Selain itu, auto &&tidak menjamin bahwa objek juga dapat dimodifikasi. Diberikan sebuah constobjek atau referensi, itu akan menyimpulkan const. Namun, modifiabilitas sering diasumsikan, mengingat konteks spesifiknya.

auto &dan auto const &sedikit lebih spesifik:

  • auto &menjamin bahwa Anda membagikan variabel dengan sesuatu yang lain. Itu selalu menjadi referensi dan tidak pernah bersifat sementara.

  • auto const &seperti itu auto &&, tetapi menyediakan akses hanya-baca.

Bagaimana dengan tipe primitif / non-primitif?

Tidak ada perbedaan.

Apakah ini juga berlaku untuk loop berdasarkan loop?

Iya. Menerapkan prinsip di atas,

  • Gunakan auto &&untuk kemampuan mengubah dan membuang nilai urutan dalam loop. (Artinya, kecuali penampung menyediakan tampilan hanya-baca, seperti std::initializer_list, dalam hal ini akan secara efektif menjadi auto const &.)
  • Gunakan auto &untuk mengubah nilai urutan dengan cara yang berarti.
  • Gunakan auto const &untuk akses hanya baca.
  • Gunakan autountuk bekerja dengan salinan (dapat dimodifikasi).

Anda juga menyebutkan auto consttanpa referensi. Ini berfungsi, tetapi tidak terlalu umum digunakan karena jarang ada keuntungan dari akses hanya-baca ke sesuatu yang sudah Anda miliki.

Potatoswatter
sumber
Sutter mengatakan bahwa auto & track constness
Jesse Pepper
1
@Bayu_joo (Ini agak aneh untuk menarik otoritas.) Apakah Anda mengacu pada bagian tertentu dari ini?
Potatoswatter
Intinya auto&sepertinya menjadi pilihan yang baik. Tapi gunakan const auto&saat Anda ingin menambahkan konstanta yang belum ada. auto&&adalah untuk penerusan, yang menurut saya terjadi lebih sering daripada yang diperkirakan Sutter. Misalnya, Anda mungkin ingin menyimpan nilai kembali auto&&dan kemudian "meneruskan" ke dua hal, seperti std :: cout untuk melihat nilai untuk debugging dan juga meneruskannya ke beberapa fungsi lain. Saya biasa menggunakan auto && lebih sering tetapi pernah digigit olehnya sekali atau dua kali ketika melakukan beberapa hal yang tidak terduga. Saya berharap saya lebih memperhatikan apa yang salah!
Jesse Pepper
@JessePepper Ya, auto&&ini terkait dari fitur bahasa yang hilang, yang harus memungkinkan pernyataan apapun untuk dibagi ke dalam laporan yang lebih kecil. Bagian yang hilang adalah perpanjangan seumur hidup ... Saya berusaha keras untuk memperbaikinya tetapi tidak ada yang memperhatikan. Jangan menaruh terlalu banyak saham dalam punditry :)
Potatoswatter
Pada auto const: Mungkin lebih alami untuk menulis auto const x = fn (); jika Anda tahu bahwa fungsi tersebut tidak mengembalikan referensi, dan Anda ingin objek x tidak berubah, untuk menghindari bug, atau mendokumentasikan penggunaannya dalam cakupan. Dengan cara yang sama Anda biasanya tidak akan menulis: const int & x = 1; Tapi auto const & memberikan hasil yang setara karena aturan perpanjangan seumur hidup untuk referensi yang dideklarasikan dengan cara ini.
Spacen Jasset
47

Ya, itu benar untuk digunakan autodan auto&untuk variabel lokal. Saat mendapatkan tipe kembalian dari suatu fungsi, itu juga benar untuk digunakan auto&. Ini juga berlaku untuk loop berbasis loop.

Aturan umum untuk penggunaan autoadalah:

  • Pilih auto xkapan Anda ingin mengerjakan salinan.
  • Pilih auto &xkapan Anda ingin bekerja dengan item asli dan dapat memodifikasinya.
  • Pilih auto const &xkapan Anda ingin bekerja dengan item asli dan tidak akan memodifikasinya.

Anda dapat membaca lebih lanjut tentang penentu otomatis di sini .

hantu
sumber
10

automenggunakan mekanisme yang sama dari jenis deduksi sebagai template, satu-satunya pengecualian yang saya sadari adalah bahwa daftar brace-init, yang disimpulkan oleh autoas std::initializer_list, tetapi tidak disimpulkan dalam konteks template.

auto x = expression;

bekerja dengan terlebih dahulu menghapus semua referensi dan kualifikasi cv dari jenis ekspresi sisi kanan, lalu mencocokkan jenisnya. Misalnya, jika Anda memiliki const int& f(){...}kemudian auto x = f();menyimpulkan xsebagai int, dan tidak const int& .

Bentuk lainnya,

auto& x = expression

tidak menghapus kualifikasi cv, jadi, dengan menggunakan contoh di atas, auto& x = f()menyimpulkan xsebagai const int&. Kombinasi lainnya hanya menambahkan kualifikasi cv.

Jika Anda ingin tipe Anda selalu disimpulkan dengan kualifikasi cv-ref, gunakan infamous decltype(auto)di C ++ 14, yang menggunakan decltypeaturan pengurangan tipe.

Jadi singkatnya kalau mau copy pakai auto. Kalau mau referensinya pakai auto&. Gunakan constkapan pun Anda menginginkan tambahan const-ness.


EDIT Ada kasus penggunaan tambahan,

auto&& x = expression;

yang menggunakan aturan referensi-menciutkan, sama seperti dalam kasus referensi penerusan dalam kode template. Jika expressionadalah nilai l, maka xadalah referensi nilai l dengan kualifikasi cv dari expression. Jika expressionrvalue, maka xrvalue referensi.

vsoftco
sumber
@Potatoswatter Terima kasih, diedit. Saya benar-benar bertanya-tanya tentang cv untuk rvalues. Apakah ada cara pengujian yang sederhana? Dan bagaimana Anda bisa memiliki nilai r yang memenuhi syarat cv? On function return cv akan dibuang.
vsoftco
Tidak, itu tidak dibuang saat mengembalikan fungsi. Ini dibuang untuk prvalues ​​dari semua jenis skalar (C ++ 14 [dan edisi lain] §5 / 6). Anda bisa mendapatkannya menggunakan panggilan fungsi atau notasi cor. Nilai x yang memenuhi syarat Cv berfungsi sama dengan yang lainnya: auto && x = std::move< const int >( 5 );akan mendeklarasikan int const && x, meskipun jarang digunakan.
Potatoswatter
@Potatoswatter terima kasih, kamu benar, kesalahanku. Saya menguji pertama dengan POD, dalam hal ini cv dibuang, dan berpikir itu kasus umum. Tentu saja tidak boleh dibuang, karena secara umum seseorang mungkin ingin mempertahankan cv (misalnya, seseorang tidak dapat memanggil fungsi anggota non-const pada pengembalian rvalue).
vsoftco
Dibuang untuk jenis skalar. POD mungkin berupa kelas. Bagaimanapun, ini adalah sudut hack dari perpotongan model ekspresi dan model objek.
Potatoswatter
2

Saat membuat variabel lokal, apakah benar menggunakan (const) auto & atau auto?

Iya. Auto tidak lebih dari tipe deduksi kompiler, jadi gunakan referensi di mana Anda biasanya menggunakan referensi, dan salinan lokal (otomatis) di mana Anda biasanya menggunakan salinan lokal. Apakah referensi akan digunakan atau tidak terlepas dari pengurangan jenis.

Di mana SomeMethod () mengembalikan nilai non-primitif - mungkin tipe lain yang ditentukan pengguna. Pemahaman saya adalah bahwa const auto & result benar karena hasil yang dikembalikan oleh SomeMethod () akan memanggil konstruktor salinan untuk jenis yang dikembalikan. Tolong koreksi saya jika saya salah.

Hukum? Ya, dengan const tersebut. Praktek terbaik? Mungkin tidak, tidak. Setidaknya, tidak dengan C ++ 11. Terutama, jika nilai yang dikembalikan dari SomeMethod () sudah bersifat sementara. Anda ingin mempelajari semantik pemindahan C ++ 11, penghapusan salinan, dan pengoptimalan nilai pengembalian: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by- nilai/

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

https://isocpp.org/wiki/faq/ctors#return-by-value-optimization

Bagaimana dengan tipe primitif? Saya berasumsi const auto sum = 1 + 2; benar.

Ya, ini bagus.

Apakah ini juga berlaku untuk loop berdasarkan loop?

untuk (const auto & object: objek)

Ya, ini juga bagus. Saya menulis kode semacam ini di tempat kerja sepanjang waktu.

tweej
sumber