Berapa banyak terlalu banyak dengan kata kunci otomatis C ++ 11?

218

Saya telah menggunakan autokata 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 autobisa digunakan secara berlebihan, karena suatu jenis sering kali merupakan bentuk dokumentasi dan pemeriksaan kewarasan. Di mana Anda menarik garis dalam menggunakan autodan 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 .

Alan Turing
sumber
Ini adalah situs tanya jawab, bukan situs diskusi. Anda mengajukan pertanyaan yang sangat umum dan saya ragu ada orang yang bisa memberi Anda sesuatu selain yang sangat subyektif. (itu sebabnya -1)
TravisG
15
@ heishe, saya menambahkan klarifikasi. Jika Anda membaca pertanyaan secara umum, pertanyaan itu tampaknya meminta pendapat subjektif, tetapi sungguh jika Anda menggunakan autokata kunci, maka Anda tahu bagaimana kata itu seharusnya digunakan. Itulah yang saya tanyakan, sebagai orang yang baru mengenal fitur ini, bagaimana saya harus menggunakannya?
Alan Turing
13
Saya telah melihat diskusi ini di semua tempat ketika C # diperkenalkan var(yaitu, setelah orang memahami bahwa itu bukan pengetikan yang dinamis). Jika mau, Anda dapat mulai dengan pertanyaan ini dan menelusuri pertanyaan terkait.
R. Martinho Fernandes
2
@Lex: Entah ada sesuatu yang legal atau tidak; menyebut sesuatu "buruk" yang legal bersifat subjektif menurut definisi. Yaitu, menyebut 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. /
shrug
3
Ramuan Sutter melihat tentang masalah ini: herbalutter.com/2013/06/13/…
rafak

Jawaban:

131

Saya pikir orang harus menggunakan autokata kunci kapan pun sulit mengatakan bagaimana cara menulis jenisnya pada pandangan pertama, tetapi jenis sisi kanan suatu ungkapan sudah jelas. Misalnya, menggunakan:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

untuk mendapatkan tipe kunci komposit boost::multi_index, meskipun Anda tahu itu int. Anda tidak bisa hanya menulis intkarena itu bisa diubah di masa depan. Saya akan menulis autodalam kasus ini.

Jadi, jika autokata kunci meningkatkan keterbacaan dalam kasus tertentu, maka gunakan. Anda dapat menulis autoketika jelas bagi pembaca jenis apa yang autodiwakilinya.

Berikut ini beberapa contohnya:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)
Kirill V. Lyadvinsky
sumber
18
Itu sepertinya bukan rekomendasi yang sangat bagus. Seberapa sering Anda tidak tahu jenis objeknya? (Di luar template, itu.) Dan jika Anda tidak tahu mereka mengetik, cari itu, jangan malas dan gunakan otomatis.
Paul Manta
9
@ Paul: sering kali Anda hanya tahu atau hanya perlu mengetahui bagian paling penting dari jenis ini, misalnya bahwa itu adalah iterator, tetapi Anda tidak tahu dan tidak peduli apakah itu adalah iterator vektor atau iterator yang ditautkan daftar; dalam kasus tersebut, Anda benar-benar tidak ingin menghabiskan waktu dan ruang layar mencoba mencari cara untuk menulis jenis.
Lie Ryan
45
Apakah C ++ diehards akan suka atau tidak, C ++ 0x akan menarik orang yang tidak akan pernah menggunakan C ++. Dan mereka akan menggunakan otomatis di semua tempat.
Prof. Falken
6
@ R.MartinhoFernandes - tidak, satu-satunya hal yang jelas adalah apa pun yang bla() Anda kembalikan foo.
Luis Machuca
8
@LuisMachuca jawaban saya adalah cara yang tidak sopan untuk mengatakan bahwa tidak jujur ​​untuk memberikan contoh buku teks variabel buruk dan penamaan fungsi dan menyalahkan kurangnya keterbacaan pada jenis inferensi.
R. Martinho Fernandes
62

Gunakan di automana pun Anda bisa — khususnya const autoagar 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 mana autotidak layak, Anda dapat menggunakan decltypeuntuk mengekspresikan tipe secara semantik sebagai kontrak berdasarkan ekspresi. Kode Anda akan terlihat berbeda, tetapi itu akan menjadi perubahan positif.

Jon Purdy
sumber
12
Saya akan mengatakan khususnya 'const auto &'
Viktor Sehr
2
Penggunaan yang lebih baik auto&&dalam situasi kompleks edmundv.home.xs4all.nl/blog/2014/01/28/…
KindDragon
2
@IndDragon: Itu adalah aturan praktis yang bagus, tapi saya lebih suka menggunakan const auto&atau const autokecuali saya secara eksplisit ingin bermutasi atau pindah.
Jon Purdy
" Gunakan otomatis di mana pun Anda bisa ". Apakah ini berarti saya harus menulis auto str = std::string();bukan std::string str;?
Calmarius
4
Menggunakan otomatis di semua tempat akan membuat kode Anda lebih mudah dibaca dan lebih sulit untuk di-debug karena Anda harus menyimpulkan sendiri jenis-jenisnya saat membaca kode.
SubMachine
52

Mudah. Gunakan saat Anda tidak peduli apa jenisnya. Sebagai contoh

for (const auto & i : some_container) {
   ...

Yang saya pedulikan di sini iadalah apa pun yang ada di wadah.

Ini agak seperti typedef.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

Di sini, saya tidak peduli apakah hdan wmengapung atau ganda, hanya saja mereka adalah tipe apa pun yang cocok untuk mengekspresikan ketinggian dan berat .

Atau pertimbangkan

for (auto i = some_container .begin (); ...

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 casting std::functiontetapi 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 menggunakannya autountuk 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):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

Di sini kita TIDAK peduli apa tipenya, jadi kita harus menulis Someclass i;danfor(unsigned x = y;...

Spraff
sumber
1
Um Tidak begitu mudah. Ini mengkompilasi dan berjalan, dan Anda baru saja menembak diri Anda sendiri di kaki jika item adalah objek nontrivial - iterasi Anda memanggil copy constructor dan destructor pada setiap langkah iterasi. Jika Anda akan membabi buta menggunakan otomatis dalam iterator berbasis rentang, itu mungkin harus "untuk (const & item: some_container)" bukan "untuk (item otomatis: some_container)".
Don Hatch
2
Tidak selalu, tetapi ok Anda mungkin ingin referensi. Terus? Itu tidak ada hubungannya dengan auto.
spraff
Saya benar-benar tidak mengerti komentar terakhir Anda. Saya mencoba menjelaskan mengapa strategi Anda tidak terlihat sangat bagus bagi saya dan mengapa saya merendahkannya.
Don Hatch
5
Saya mengatakan bahwa apakah Anda menggunakan referensi atau tidak itu ortogonal untuk apakah Anda menggunakan otomatis atau tidak. Saya akan mengeditnya untuk menambahkan referensi karena memang itulah yang biasanya ingin dilakukan, tetapi sama sekali tidak relevan dengan topik yang dibahas.
spraff
43

Lakukan untuk itu. Gunakan di automana 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

auto foo = bla();

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 automenyelamatkan 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.

DarW
sumber
38

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 digunakanauto . Lewati ke menit 25:03 untuk diskusi 4 menit. Ketiga pembicara memberikan poin yang sangat baik yang harus diingat saat tidak digunakan auto.

Saya sangat mendorong orang untuk sampai pada kesimpulan mereka sendiri, tetapi yang saya ambil adalah untuk digunakan di automana-mana kecuali :

  1. Itu menyakitkan keterbacaan
  2. Ada kekhawatiran tentang konversi tipe otomatis (mis. Dari konstruktor, penugasan, tipe perantara template, konversi implisit antara lebar integer)

Penggunaan liberal explicitmembantu 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 di autotempat lain."

Sean
sumber
4
Mungkin juga layak untuk ditautkan ke "hampir selalu otomatis" - herbalutter.com/2013/08/12/…
Rob Starling
37

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 autoakan berhasil:

   for(auto i = container.begin(); i != container.end(); ++i);

auto di sini tidak ada salahnya dibaca.

Contoh lain adalah tipe aturan parser, yang bisa panjang dan berbelit-belit. Membandingkan:

   auto spaces = space & space & space;

dengan

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

Di sisi lain, ketika jenis diketahui dan sederhana, akan jauh lebih baik jika dinyatakan secara eksplisit:

int i = foo();

daripada

auto i = foo();
Gene Bushuyev
sumber
2
Tentu saja, memiliki rentang berbasis untuk loop dalam bahasa membuat contoh pertama Anda kurang menarik. 8v)
Fred Larson
@ Fred: jenisnya masih bisa rumit (Saya berpikir wadah asosiatif)
Matthieu M.
3
@Fred: Kapan saja batas Anda tidak begin()dan end(), atau ukuran langkah Anda adalah selain dari satu, atau Anda memodifikasi wadah saat Anda mengulang, pernyataan berbasis rentang untuk pernyataan tidak akan membantu Anda.
Dennis Zickefoose
6
@geotavros: Dan r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>apakah itu?
Dennis Zickefoose
7
@geotavros: Atau Anda dapat melihat jenisnya space, dan mencarinya. Bagaimanapun juga, itulah informasi yang lebih berguna ... masalahnya bukan "tipe apa variabel baru ini" melainkan "apa space & space & spaceartinya?" Jenis ekspresi yang sebenarnya hanyalah noise.
Dennis Zickefoose
19

auto bisa sangat berbahaya dalam kombinasi dengan templat ekspresi yang banyak digunakan oleh pustaka aljabar linier seperti Eigen atau OpenCV.

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

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.

auto C = Matrix(A * B); // The expression is now evaluated immediately.
morotspaj
sumber
1
Itu sepertinya perilaku yang aneh untuk memulai. Jika saya mengalikan dua matriks, bahkan jika operasi ini malas, saya tidak akan berharap itu dapat dievaluasi kembali, saya berharap itu akan mempertahankan keadaan yang dievaluasi setelah evaluasi awal. Jika Anda ingin mengubah parameter tanpa mengubah parameter asli, bukankah Anda akhirnya harus membangun kembali ekspresi? Atau apakah itu dirancang untuk situasi pemrosesan streaming, di mana parameter asli terus berubah tetapi prosedurnya tetap sama?
JAB
1
Apakah A*Bekspresi disalin dalam autovariabel atau sesuatu yang lain, perilaku yang Anda gambarkan masih ada.
xtofl
Tidak ada bug yang disebabkan oleh penggunaan auto.
Jim Balter
@ JAB: Ini dirancang untuk mendukung penyederhanaan dan sinergi antara operasi, misalnya diag(A * B)tidak harus membuang siklus menghitung elemen-elemen off-diagonal.
Ben Voigt
Saya juga melihat kode seperti 'untuk (otomatis o: vecContainer)' di mana 'o' adalah objek berat yang akan disalin setiap saat. Rekomendasi saya adalah menggunakannya untuk apa yang awalnya dimaksudkan, yaitu templat (dengan panduan deduksi yang sulit) dan typedef yang melelahkan. Bahkan kemudian Anda harus berhati-hati dan berbeda antara otomatis dan otomatis &.
gast128
10

Saya menggunakan autobatasan wihout dan tidak menghadapi masalah. Saya bahkan kadang-kadang akhirnya menggunakannya untuk tipe sederhana seperti int. 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 mis

auto i = MyClass();

dari pada

MyClass i;

Ini adalah satu kasus di mana saya akan mengatakan itu adalah penyalahgunaan autokata 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, autotidak ada salahnya: misalnya auto s = mycollection.size(), saya dapat menebak bahwa sakan 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 dalam int_type s = mycollection.size()).

Mengenai contoh ini dari jawaban yang diterima:

for ( auto x = max_size; x > 0; --x )

Dalam kode saya, saya masih menggunakan autodalam kasus ini, dan jika saya ingin xtidak ditandatangani, maka saya menggunakan fungsi utilitas, bernama say make_unsigned, yang menyatakan dengan jelas keprihatinan saya:

for ( auto x = make_unsigned(max_size); x > 0; --x )

disclaimer: Saya hanya menjelaskan penggunaan saya , saya tidak kompeten untuk memberikan saran!

rafak
sumber
1
@ChristianRau: bukan sarkastik. Perhatikan bahwa saya tidak merekomendasikan penggunaannya auto i = MyClass().
rafak
3
Tindak lanjut: lihat: herbalutter.com/2013/06/13/… . Penggunaan mis as_unsigneddirekomendasikan di sana, atau bahkan auto w = widget{};.
rafak
3

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 ++:

int main() {
    int x;
    int y = 0;
    y += x;
}

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.

main.cpp: Dalam fungsi 'int main ()':

main.cpp: 4: 8: peringatan : 'x' digunakan tidak diinisialisasi dalam fungsi ini [-Wuninitialized]

y + = x;

    ^

================================================== =============================== Sekarang jika kita mengubah program kita yang menggunakan otomatis , maka kompilasi kita mendapatkan yang berikut:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: Dalam fungsi 'int main ()':

main.cpp: 2: 10: error : pernyataan 'auto x' tidak memiliki penginisialisasi

 auto x;

      ^

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

Mantosh Kumar
sumber
2
Iya. Dan untuk menentukan jenisnya Anda dapat menginisialisasi sebagai 0i, 0u, 0l, 0ul, 0.0f, 0.0, atau bahkan int (), unsigned (), double (), dll.
Robinson
6
Argumen ini konyol. Anda mengatakan "Anda tidak bisa melupakan penginisialisasi karena Anda akan mendapatkan kesalahan penyusun", tetapi itu mengharuskan Anda untuk ingat untuk menggunakannya auto.
Lightness Races dalam Orbit
1
@LightnessRacesinOrbit: Saya menyadari (mempelajari) konsep ini dari pembicaraan Herb Sutter. Saya menemukan saran logis / praktis dari ramuan herbal, maka saya pikir untuk berbagi dengan masyarakat.
Mantosh Kumar
2
Saya rasa ini bukan motivasi yang baik untuk menggunakan mobil. Nyalakan tanda peringatan kompiler Anda untuk menggunakan variabel yang tidak diinisialisasi dan alamat semua peringatan. Itu tidak berarti Anda tidak boleh menggunakan auto- tetapi Anda tidak perlu untuk menghindari masalah ini.
einpoklum
2

Satu bahaya yang saya perhatikan adalah dalam hal referensi. misalnya

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

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.

auto another_ref = function_returning_ref_to_big_object();

Anda memerlukan "otomatis &" atau "otomatis & &"

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();
pengguna2495422
sumber
1

Gunakan autojika 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.

LainIwakura
sumber
4
"Di mana masuk akal ..." adalah bagian yang sulit. Pemrogram dapat begitu terperangkap dalam rincian pengkodean, mereka kehilangan akal tentang apa yang masuk akal bagi pemrogram lain khususnya pengelola masa depan.
DarenW
Itu benar, meskipun saya pikir cukup mudah untuk mengatakan kapan itu ambigu. Jika ragu, gunakan komentar!
LainIwakura
1
Tidakkah masuk akal untuk menggunakan suatu tipe?
Mikhail
Beberapa pengembang akan mengatakan bahwa jenisnya harus selalu disimpulkan!
Arafangion
Gunakan komentar ...... atau cukup gunakan tipe dan tidak perlu komentar?
user997112
1

autokata 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, sizeofmelaporkannya dengan benar, decltypeakan memberikan jenis yang benar - tidak ada salahnya. Saya tidak dihitung autosebagai terlalu sering digunakan!

Ajay
sumber
0

TL; DR: Lihat aturan praktis di bagian bawah.

The jawaban yang diterima menunjukkan aturan berikut praktis:

Gunakan autokapan pun sulit untuk mengatakan bagaimana menulis jenis pada pandangan pertama, tetapi jenis sisi kanan ekspresi jelas.

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:

auto x = f();

Apa yang menjadikan ini contoh penyalahgunaan auto? Apakah ini ketidaktahuan saya tentang f()tipe pengembalian? Yah, memang mungkin bisa membantu jika saya mengetahuinya, tapi - itu bukan perhatian utama saya. Apa yang lebih dari masalah adalah itu xdan f()sangat tidak berarti. Jika kita punya:

auto nugget = mine_gold();

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 autokapan pun kompiler mengizinkannya, kecuali:

  • Anda merasa nama variabel bersama dengan inisialisasi / ekspresi penugasan tidak memberikan informasi yang cukup tentang apa yang dilakukan pernyataan itu.
  • Anda merasakan nama variabel bersama dengan inisialisasi / ekspresi penugasan memberikan informasi "menyesatkan" tentang apa yang seharusnya menjadi tipe - yaitu, jika Anda harus menebak apa yang datang alih-alih otomatis Anda akan dapat menebak - dan itu akan menjadi salah, dan asumsi salah ini berakibat belakangan dalam kode.
  • Anda ingin memaksakan tipe yang berbeda (misalnya referensi).

Dan juga:

  • Lebih suka memberikan nama yang bermakna (yang tidak mengandung nama jenis tentu saja) sebelum mengganti autodengan tipe konkret.
einpoklum
sumber
-3

Salah satu pengalaman pahit saya autoadalah menggunakannya dengan ekspresi lambda :

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

Sebenarnya, di sini idiselesaikan untuk fungsi pointer int(*)(). Ini hanya sederhana cout, tetapi bayangkan seperti apa kesalahan kompilasi / runtime buruk yang dapat menyebabkannya ketika digunakan template.

Anda harus menghindari auto dengan ekspresi seperti itu dan memasukkan returntipe yang tepat (atau dikendalikan decltype())

Penggunaan yang benar untuk contoh di atas adalah,

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  
iammilind
sumber
7
Anda melakukan pekerjaan yang mengerikan untuk menjelaskan apa yang harus dilakukan dengan mobil. Anda membuat fungsi dan kemudian mencetaknya ... Oke?
Dennis Zickefoose
5
@ iammilind: dan apa hubungannya dengan auto?
R. Martinho Fernandes
7
Saya merasa sangat tidak mungkin bahwa seseorang ingin memasukkan ()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.
R. Martinho Fernandes
4
Dapatkah Anda setidaknya menggambarkan skenario di mana auto x = []() { /* .... whatever goes in here ... */ }()lebih baik daripada auto x = /* .... whatever goes in here ... */;, yaitu hal yang sama, tanpa lambda? Saya menemukan itu agak sia-sia, karena alasan yang sama auto x = 42 + y - 42tidak ada gunanya.
R. Martinho Fernandes
6
-1 ini bukan kesalahan otomatis. Jenis lambda tidak bisa dieja jadi otomatis diperlukan , jika Anda lupa memanggil fungsi maka itu adalah pencarian Anda sendiri! Anda bisa meletakkan pointer fungsi yang tidak dipanggil ke dalam printf C seperti sembarangan.
spraff