Saya sudah pemrograman dalam C ++ untuk sementara waktu sekarang, tetapi sebagian besar hal berpusat di sekitar fitur tingkat rendah C ++. Maksud saya sebagian besar bekerja dengan pointer dan array mentah. Saya pikir perilaku ini dikenal sebagai menggunakan C ++ sebagai C dengan kelas. Meskipun demikian, saya baru mencoba C baru-baru ini untuk pertama kalinya. Saya terkejut bagaimana bahasa seperti C # dan Java menyembunyikan detail-detail ini di kelas perpustakaan standar yang nyaman seperti Kamus dan Daftar.
Saya sadar bahwa pustaka standar C ++ memiliki banyak wadah seperti vektor, peta dan string juga dan C ++ 11 hanya menambah ini dengan memiliki std :: array dan rentang loop.
Bagaimana cara terbaik saya belajar memanfaatkan fitur-fitur bahasa modern ini dan mana yang cocok untuk saat-saat mana? Benarkah rekayasa perangkat lunak dalam C ++ saat ini sebagian besar bebas dari manajemen memori manual?
Terakhir, kompiler mana yang harus saya gunakan untuk memaksimalkan standar baru? Visual Studio memiliki alat debugging yang sangat baik, tetapi bahkan VS2012 tampaknya memiliki dukungan C ++ 11 yang mengerikan.
g++ -std=c++11
Jawaban:
Pertama, beberapa aturan praktis:
Gunakan
std::unique_ptr
sebagai smart pointer yang tidak ada overhead. Anda tidak perlu repot dengan pointer mentah terlalu sering.std::shared_ptr
juga tidak perlu dalam banyak kasus. Keinginan untuk memiliki kepemilikan bersama seringkali mengkhianati kurangnya pemikiran tentang kepemilikan.Gunakan
std::array
untuk array panjang statis danstd::vector
untuk dinamis.Gunakan algoritma generik secara luas, khususnya:
<algorithm>
<numeric>
<iterator>
<functional>
Gunakan
auto
dan didecltype()
mana pun mereka mendapat manfaat keterbacaan. Khususnya, ketika Anda ingin mendeklarasikan sesuatu, tetapi dari tipe yang tidak Anda pedulikan seperti iterator atau tipe templat yang kompleks, gunakanauto
. Ketika Anda ingin mendeklarasikan sesuatu dalam hal jenis hal lain, gunakandecltype()
.Jadikan hal-hal menjadi aman ketika Anda bisa. Ketika Anda memiliki pernyataan yang menerapkan invarian pada hal tertentu, logika itu dapat dipusatkan dalam suatu tipe. Dan ini tidak selalu membuat overhead runtime. Itu juga harus pergi tanpa mengatakan bahwa gips C-style (
(T)x
) harus dihindari untuk gips C ++-style yang lebih eksplisit (dan dapat dicari!) (Misalnya,static_cast
).Terakhir, ketahuilah bagaimana aturan tiga:
Sudah menjadi aturan lima dengan penambahan move constructor dan move assignment operator. Dan pahami rvalue referensi secara umum dan cara menghindari penyalinan.
C ++ adalah bahasa yang kompleks, sehingga sulit untuk menggambarkan cara terbaik untuk menggunakan semua itu. Namun praktik pengembangan C ++ yang baik belum berubah secara mendasar dengan C ++ 11. Anda masih harus lebih memilih wadah yang dikelola memori daripada manajemen memori manual — pointer pintar membuatnya mudah untuk melakukan ini secara efisien.
Saya akan mengatakan bahwa C ++ modern memang sebagian besar bebas dari manajemen memori manual - keuntungan dari model memori C ++ adalah bahwa itu deterministik , bukan manual. Alokasi yang dapat diprediksi menjadikan kinerja yang lebih dapat diprediksi.
Adapun kompiler, G ++ dan Dentang keduanya kompetitif dalam hal fitur C ++ 11, dan dengan cepat mengejar kekurangan mereka. Saya tidak menggunakan Visual Studio, jadi saya tidak bisa berbicara atau menentangnya.
Akhirnya, catatan tentang
std::for_each
: hindari secara umum.transform
,accumulate
, Danerase
-remove_if
baik tua fungsionalmap
,fold
danfilter
. Tetapifor_each
lebih umum, dan karena itu kurang bermakna — itu tidak mengungkapkan maksud apa pun selain perulangan. Selain itu, ini digunakan dalam situasi yang sama dengan range-basedfor
, dan secara sintaksis lebih berat, bahkan ketika digunakan point-free. Mempertimbangkan:sumber
std::for_each
saya akan mengharapkan rentang berdasarkan untuk loop sebagai pengganti yang lebih baik daripada biasafor
.std::for_each
, bukan dengan berbasis rentang . Saya telah menghapusnya untuk menghindari kebingungan.std::for_each()
. Ketika Anda memiliki lambda, itu tentu lebih baik daripadafor
loop tradisional . Denganfor
loop berbasis rentang yang mungkin tidak terjadi, tetapi Anda tidak menulis "for
loop berbasis rentang ".for
loop" termasuk "for
loop berbasis rentang ". Saya telah mengedit dengan lebih banyak penjelasan dan contoh untuk menjelaskan, terima kasih.Sebagai titik awal:
char*
untuk string. Gunakanstd::string
ataustd::wstring
dan tonton saja kode Anda menjadi lebih pendek, lebih mudah dibaca, dan lebih aman[ ]
) dan gunakanstd::vector
atau kelas kontainer lain yang sesuai. Hal-hal baik tentang itustd::vector
adalah bahwa ia tahu panjangnya sendiri, itu membersihkan kontennya ketika keluar dari ruang lingkup, mudah untuk beralih, dan itu membuat dirinya lebih besar ketika Anda menambahkan lebih banyak item. Tetapi ada koleksi lain yang mungkin bekerja lebih baik untuk keadaan Anda.std::unique_ptr
- dan pelajaristd::move
segera. Karena hal ini dapat menyebabkan beberapa objek yang tidak dapat ditiru, kemalasan kadang-kadang dapat mengirim Anda ke arahstd::shared_ptr
- dan Anda mungkin memiliki beberapa kasus penggunaan aslistd::shared_ptr
jugaauto
saat mendeklarasikan iterator dan tipe yang bergantung pada deklarasi sebelumnya (mis. Sebelumnya Anda mendeklarasikan vektor sesuatu, sekarang Anda mendeklarasikan sesuatu, gunakanauto
)for_each
lebih dari "mentah untuk" kapan saja Anda bisa karena itu membuat orang lain dari membaca loop Anda dengan hati-hati untuk menyimpulkan bahwa Anda sebenarnya mengulangi seluruh koleksi dll. Jika kompiler Anda mendukung "rentang untuk" maka gunakan itufor_each
. Pelajari panggilan algoritma sepele sepertiiota
,generate
,accumulate
,find_if
dan sebagainya.Jangan terlalu sibuk dengan apa yang digunakan kompiler. Kurangnya "mengerikan, mengerikan" dukungan C ++ 11 di VS2012 adalah bahwa tidak ada template variadic (ya benar, Anda baru saja akan menggunakan template variadic) dan
{}
initializer tidak ada di sana. Saya ingin itu juga, tetapi saya hampir tidak akan berhenti menggunakan alat pengembangan yang berguna di atasnya.Hal kedua yang harus dilakukan, setelah merangkul
std::
, adalah mulai berpikir RAII. Kapan saja Anda milikiMaka yang Anda miliki adalah konstruktor, sejumlah fungsi anggota, dan destruktor. Tulis kelas yang menangani itu untuk Anda. Anda bahkan mungkin tidak perlu menulis ctor dan dtor. Menempatkan
shared_ptr
sebagai variabel anggota kelas adalah contoh RAII - Anda tidak menulis kode manajemen memori, tetapi ketika instance Anda keluar dari ruang lingkup, hal-hal yang benar akan terjadi. Perluas pemikiran itu untuk mencakup hal-hal seperti menutup file, melepaskan pegangan, kunci dll dan kode hanya akan menjadi lebih sederhana dan lebih kecil (sambil menghilangkan kebocoran) di depan mata Anda.Jika Anda merasa benar-benar percaya diri, pembersihan
printf
mendukungcout
, menyingkirkan macro (#define
barang-barang), dan mulai mempelajari beberapa "idiom canggih" seperti PIMPL. Saya memiliki seluruh kursus tentang ini di Pluralsight yang mungkin dapat Anda tonton menggunakan uji coba gratis mereka.sumber
Dengan pemrograman. Pengalaman adalah cara terbaik untuk belajar.
C ++ 11 memiliki banyak fitur baru (otomatis, nilai, pointer pintar baru - hanya untuk beberapa nama). Awal yang terbaik adalah mulai menggunakannya, dan bacalah kapan pun Anda bisa, dan kapan pun Anda menemukan artikel yang menarik.
Itu tergantung apa yang perlu Anda lakukan. Sebagian besar aplikasi dapat lolos dengan pointer cerdas, dan melupakan manajemen memori. Masih ada aplikasi yang tidak dapat lolos dengan mudah (misalnya jika mereka membutuhkan penempatan baru, atau pengalokasi memori khusus untuk alasan apa pun).
Jika Anda perlu menggunakan Qt, Anda harus menggunakan aturan mereka untuk manajemen memori.
Apa pun yang Anda miliki yang mendukung standar terbaru:
tetapi tidak ada kompiler yang mendukung semua fitur.
sumber
Universitas saya masih menggunakan C ++ untuk mengajar. Saya telah memprogram dengan C ++ selama 5 tahun dan sekarang saya adalah mahasiswa pascasarjana. Tentu saja, sekarang saya menggunakan banyak Java, Ruby dll. Saya sangat menyarankan Anda jangan terlalu terburu-buru tentang fitur-fitur dalam bahasa seperti Java. Dalam pengalaman dan pendapat saya, setelah fitur tingkat rendah C ++. Anda harus melihat ke topik seperti pemrograman umum dengan C / C ++ seperti membuat kelas template, fungsi template, operator ditulis ulang, metode virtual, pointer pintar. Untuk Bagian Desain Berorientasi Objek, ada banyak fitur yang dimiliki C ++ dan Java tidak, seperti multi-inheritance. Warisan sangat kuat tetapi juga berbahaya. Level implementasi desain berorientasi objek dalam C ++ juga merupakan topik yang bagus. Komunikasi antar proses, utas, juga penting dalam C ++.
Untuk kompiler dan debugger. Saya tahu visual studio itu luar biasa. Tapi saya sangat menyarankan Anda mempelajari GDB, Valgrind, dan Diam, dan jagokan alat ini. Microsoft memang luar biasa, tetapi itu melakukan terlalu banyak hal untuk Anda. Sebagai siswa, Anda benar-benar perlu mempelajari hal-hal yang Microsoft lakukan juga terhadap Anda. Untuk kompiler, G ++ bagus dari GNU.
Lagi pula, setelah bertahun-tahun, saya benar-benar merasa, hal yang paling penting adalah fitur tingkat rendah seperti array mentah. Vektor sebenarnya hanya array dinamis. Ini adalah rekomendasi saya, sesuatu yang mungkin terlalu subjektif, hanya mengambil apa yang Anda anggap benar.
sumber