Saya baru-baru ini belajar D dan mulai mendapatkan semacam keakraban dengan bahasa. Saya tahu apa yang ditawarkannya, saya belum tahu bagaimana menggunakan semuanya, dan saya tidak tahu banyak tentang idiom D dan sebagainya, tetapi saya sedang belajar.
Saya suka D. Ini adalah bahasa yang bagus, karena, dalam beberapa hal, pembaruan besar ke C, dan dilakukan dengan baik. Tidak ada fitur yang tampak "melesat", tetapi sebenarnya cukup dipikirkan dan dirancang dengan baik.
Anda akan sering mendengar bahwa D adalah apa C ++ harus sudah (saya meninggalkan pertanyaan apakah atau tidak itu benar kepada setiap orang untuk memutuskan diri untuk menghindari perang api yang tidak perlu). Saya juga telah mendengar dari beberapa programmer C ++ bahwa mereka menikmati D lebih dari C ++.
Saya sendiri, sementara saya tahu C, saya tidak bisa mengatakan bahwa saya tahu C ++. Saya ingin mendengar dari seseorang yang mengetahui C ++ dan D jika mereka berpikir ada sesuatu yang C ++ lakukan lebih baik daripada D sebagai bahasa (artinya bukan yang biasa "ia memiliki lebih banyak perpustakaan pihak ketiga" atau "ada lebih banyak sumber daya" atau " lebih banyak pekerjaan yang membutuhkan C ++ daripada D ada ").
D dirancang oleh beberapa programmer C ++ yang sangat terampil ( Walter Bright dan Andrei Alexandrescu , dengan bantuan komunitas D) untuk memperbaiki banyak masalah yang dimiliki C ++, tetapi apakah ada sesuatu yang sebenarnya tidak menjadi lebih baik? Sesuatu yang dia lewatkan? Sesuatu yang Anda pikir bukan solusi yang lebih baik?
Juga, perhatikan bahwa saya berbicara tentang D 2.0 , bukan D 1.0 .
sumber
Jawaban:
Sebagian besar hal yang C ++ "lakukan" lebih baik daripada D adalah hal-hal meta: C ++ memiliki kompiler yang lebih baik, alat yang lebih baik, perpustakaan yang lebih matang, lebih banyak binding, lebih banyak ahli, lebih banyak tutorial, dll. Pada dasarnya ia memiliki lebih banyak dan lebih baik dari semua hal eksternal yang Anda harapkan dari bahasa yang lebih matang. Ini tidak bisa dibantah.
Adapun bahasa itu sendiri, ada beberapa hal yang C ++ tidak lebih baik daripada D menurut saya. Mungkin ada lebih banyak, tetapi ada beberapa yang bisa saya sebutkan di atas kepala saya:
C ++ memiliki sistem tipe pemikiran yang lebih baik.
Ada beberapa masalah dengan sistem tipe dalam D saat ini, yang tampaknya merupakan kekeliruan dalam desain. Sebagai contoh, saat ini tidak mungkin untuk menyalin const struct ke non-const struct jika struct berisi referensi objek kelas atau pointer karena transitivity dari const dan cara postblit konstruktor bekerja pada tipe nilai. Andrei mengatakan dia tahu bagaimana menyelesaikan ini, tetapi tidak memberikan rincian. Masalahnya tentu bisa diperbaiki (memperkenalkan C ++ - style copy constructors akan menjadi satu perbaikan), tetapi ini adalah masalah utama dalam bahasa saat ini.
Masalah lain yang telah mengganggu saya adalah kurangnya const logis (yaitu tidak
mutable
seperti di C ++). Ini bagus untuk menulis kode thread-safe, tetapi menyulitkan (mustahil?) Untuk melakukan intialisation lazy dalam objek const (pikirkan fungsi const 'get' yang membangun dan menyimpan nilai yang dikembalikan pada panggilan pertama).Akhirnya, mengingat masalah-masalah yang ada, aku khawatir tentang bagaimana sisa sistem tipe (
pure
,shared
, dll) akan berinteraksi dengan segala sesuatu yang lain dalam bahasa setelah mereka dihukum digunakan. Pustaka standar (Phobos) saat ini sangat sedikit menggunakan sistem tipe D yang canggih, jadi saya pikir masuk akal pertanyaan apakah itu akan bertahan di bawah tekanan. Saya skeptis, tetapi optimis.Perhatikan bahwa C ++ memiliki beberapa jenis kutil sistem (mis. Konstanta non-transitif, membutuhkan
iterator
dan jugaconst_iterator
) yang membuatnya cukup jelek, tetapi sementara sistem tipe C ++ sedikit salah pada bagian-bagiannya, ia tidak menghentikan Anda menyelesaikan pekerjaan seperti D's terkadang demikian.Sunting: Untuk memperjelas, saya percaya bahwa C ++ memiliki sistem tipe pemikiran yang lebih baik - belum tentu yang lebih baik - jika itu masuk akal. Pada dasarnya, di DI merasa bahwa ada risiko yang terlibat dalam menggunakan semua aspek dari sistem tipenya yang tidak ada dalam C ++.
D kadang-kadang sedikit terlalu nyaman.
Satu kritik yang sering Anda dengar tentang C ++ adalah bahwa ia menyembunyikan beberapa masalah tingkat rendah dari Anda, mis. Penugasan sederhana seperti
a = b;
dapat melakukan banyak hal seperti memanggil operator konversi, memanggil operator penugasan yang berlebihan dll, yang dapat berupa sulit dilihat dari kodenya. Beberapa orang seperti ini, beberapa orang tidak. Either way, di D itu lebih buruk (lebih baik?) Karena hal-hal sepertiopDispatch
,@property
,opApply
,lazy
yang memiliki potensi untuk mengubah kode melihat tidak bersalah dalam hal-hal yang tidak Anda harapkan.Saya tidak berpikir ini adalah masalah besar secara pribadi, tetapi beberapa mungkin menemukan ini mengesampingkan.
D memerlukan pengumpulan sampah.
Ini dapat dilihat sebagai kontroversial karena dimungkinkan untuk menjalankan D tanpa GC. Namun, hanya karena itu mungkin bukan berarti itu praktis. Tanpa GC, Anda kehilangan banyak fitur D, dan menggunakan perpustakaan standar akan seperti berjalan di ladang ranjau (siapa yang tahu fungsi mana yang mengalokasikan memori?). Secara pribadi, saya pikir itu benar-benar tidak praktis untuk menggunakan D tanpa GC, dan jika Anda bukan penggemar GCs (seperti saya) maka ini bisa sangat mengecewakan.
Definisi array naif dalam D mengalokasikan memori
Ini adalah hewan peliharaan kesayangan saya:
Tampaknya, untuk menghindari alokasi dalam D, Anda harus melakukan:
Alokasi 'di belakang Anda' kecil ini adalah contoh yang baik dari dua poin saya sebelumnya.
Sunting: Perhatikan bahwa ini adalah masalah yang diketahui sedang dikerjakan.Sunting: Ini sekarang sudah diperbaiki. Tidak ada alokasi yang dilakukan.
Kesimpulan
Saya telah memfokuskan pada hal negatif dari D vs C ++ karena itulah pertanyaan yang diajukan, tetapi tolong jangan melihat posting ini sebagai pernyataan bahwa C ++ lebih baik dari D. Saya dapat dengan mudah membuat posisi tempat yang lebih besar di mana D lebih baik dari pada C ++. Terserah Anda untuk membuat keputusan mana yang akan digunakan.
sumber
Ketika saya bergabung dengan pengembangan D, saya berada dalam posisi yang aneh untuk menjadi salah satu orang yang paling tahu tentang C ++. Sekarang saya berada dalam posisi yang bahkan lebih aneh untuk menjadi salah satu dari orang-orang yang paling tahu tentang D. Saya tidak mengatakan ini untuk kredit yang sesuai atau hak-hak menyombongkan diri dengan mengatakan saya berada dalam rasa ingin tahu posisi yang diuntungkan untuk menjawab pertanyaan ini. Hal yang sama berlaku untuk Walter.
Pada umumnya, menanyakan apa yang dilakukan C ++ (dan maksud saya C ++ 2011) lebih baik daripada D sama kontradiktifnya dengan pertanyaan, "Jika Anda membayar seorang profesional untuk membersihkan rumah Anda, tempat apa yang akan mereka tinggalkan lebih kotor dari sebelumnya? " Apa pun nilainya bahwa C ++ dapat melakukan itu D tidak bisa, itu selalu berdiri seperti jempol sakit bagi saya dan Walter, jadi hampir secara definisi tidak ada yang bisa dilakukan C ++ yang tidak dalam jangkauan D.
Satu hal yang jarang dipahami dalam desain bahasa (karena sedikit orang yang beruntung untuk benar-benar melakukan beberapa) adalah bahwa ada kesalahan unforced jauh lebih sedikit daripada yang mungkin muncul. Banyak dari kita pengguna bahasa melihat beberapa konstruk dan yang lain dan berkata, "Eh! Ini sangat salah! Apa yang mereka pikirkan?" Faktanya adalah bahwa contoh paling canggung dalam suatu bahasa adalah setelah beberapa keputusan mendasar yang semuanya sehat dan diinginkan tetapi secara fundamental saling bersaing atau bertentangan satu sama lain (misalnya modularitas dan efisiensi, kesederhanaan dan kontrol dll).
Dengan semua ini dalam pikiran, saya akan menyebutkan beberapa hal yang dapat saya pikirkan, dan untuk masing-masing saya akan menjelaskan bagaimana pilihan D berasal dari keinginan untuk memenuhi piagam lain yang lebih tinggi.
D menganggap semua objek dapat dipindahkan dengan menyalin bitwise. Ini meninggalkan sebagian kecil desain ke C ++, khususnya yang menggunakan pointer internal, yaitu kelas yang mengandung pointer di dalamnya. (Setiap desain seperti itu dapat diterjemahkan tanpa atau dengan biaya efisiensi yang dapat diabaikan ke dalam D, tetapi akan ada upaya penerjemahan yang terlibat.) Kami membuat keputusan ini untuk sangat menyederhanakan bahasa, membuat penyalinan objek lebih efisien tanpa intervensi pengguna atau minimal, dan menghindari seluruh salinan konstruksi moril dan fitur referensi nilai sama sekali.
D melarang jenis-jenis ambigu-jender (yang tidak dapat memutuskan apakah itu tipe nilai atau tipe referensi). Desain seperti itu dengan suara bulat dijauhi dalam C ++ dan hampir selalu salah, tetapi beberapa dari mereka secara teknis benar. Kami membuat pilihan ini karena sebagian besar melarang kode yang salah dan hanya sebagian kecil kode yang benar yang dapat dirancang ulang. Kami percaya ini adalah tradeoff yang bagus.
D melarang hierarki multi-root. Poster sebelumnya di sini menjadi sangat bersemangat tentang topik khusus ini, tetapi ini adalah landasan yang sudah dilalui dengan baik dan tidak ada keuntungan nyata dari hierarki tanpa akar dibandingkan hierarki yang semuanya memiliki akar yang sama.
Dalam D Anda tidak bisa melempar misalnya int. Anda harus melempar objek yang mewarisi Throwable. Tidak ada kontes keadaan yang lebih baik di D, tapi, well, itu satu hal C ++ bisa melakukan itu D tidak bisa.
Dalam C ++ unit enkapsulasi adalah kelas. Dalam D itu adalah modul (yaitu file). Walter membuat keputusan ini karena dua alasan: untuk secara alami memetakan enkapsulasi ke semantik perlindungan sistem, dan untuk meniadakan kebutuhan akan "teman". Pilihan ini terintegrasi sangat baik dalam desain modularitas keseluruhan D. Dimungkinkan untuk mengubah sesuatu menjadi lebih seperti C ++, tetapi itu akan memaksa hal-hal; Pilihan lingkup enkapsulasi C ++ hanya baik untuk desain fisik C ++.
Mungkin ada satu atau dua hal yang lebih kecil, tetapi secara keseluruhan ini seharusnya.
sumber
Object*
banyak digunakan sebagaiint*
?) Dan D tampaknya sepenuhnya mengabaikan penalti kinerja, atau mengklaimnya tidak ada. Itu jelas salah - cache miss cukup terlihat dalam banyak kasus, jadi C ++ akan selalu memiliki keunggulan fleksibilitas lebih dari D.Saya pikir Anda akan kesulitan menemukan banyak D yang objektiflebih buruk dari C ++. Sebagian besar masalah dengan D di mana Anda bisa secara objektif mengatakan itu lebih buruk adalah kualitas masalah implementasi (yang umumnya disebabkan oleh seberapa muda bahasa dan implementasi dan telah diperbaiki pada kecepatan sangat tinggi akhir-akhir ini), atau mereka masalah dengan kekurangan perpustakaan pihak ke-3 (yang akan datang seiring waktu). Bahasa itu sendiri umumnya lebih baik daripada C ++, dan kasus-kasus di mana C ++, sebagai bahasa, lebih baik umumnya akan menjadi tempat ada tradeoff di mana C ++ pergi ke satu arah dan D pergi ke arah lain, atau di mana seseorang memiliki alasan subjektif mengapa mereka berpikir bahwa yang satu lebih baik dari yang lain. Tetapi jumlah alasan obyektif langsung mengapa C ++, sebagai bahasa, lebih baik cenderung sedikit dan jarang.
Sebenarnya, saya harus benar-benar merusak otak saya untuk mencari alasan mengapa C ++, sebagai bahasa, lebih baik daripada D. Apa yang biasanya terlintas dalam pikiran adalah masalah pertukaran.
Karena konstanta D adalah transitif, dan karena bahasanya memiliki kekal , ia memiliki jaminan yang jauh lebih kuat daripada C ++
const
, yang berarti bahwa D tidak dan tidak dapat dimilikimutable
. Tidak dapat memiliki const logis . Jadi, Anda mendapatkan keuntungan besar dengan sistem const D, tetapi dalam beberapa situasi, Anda tidak bisa menggunakanconst
seperti yang Anda miliki di C ++.D hanya memiliki satu operator cast, sedangkan C ++ memiliki 4 (5 jika Anda menghitung operator cast C). Hal ini membuat berurusan dengan pemain di D lebih mudah dalam kasus umum, tetapi bermasalah ketika Anda benar - benar menginginkan komplikasi / manfaat tambahan yang
const_cast
disediakan oleh saudara-saudaranya. Tapi D sebenarnya cukup kuat sehingga Anda bisa menggunakan templat untuk mengimplementasikan gips C ++, jadi jika Anda benar-benar menginginkannya, Anda dapat memilikinya (dan mereka bahkan mungkin berakhir di pustaka standar D di beberapa titik).D memiliki jauh lebih sedikit gips implisit daripada C ++ dan jauh lebih mungkin untuk menyatakan bahwa dua fungsi bertentangan satu sama lain (memaksa Anda untuk lebih spesifik tentang fungsi yang Anda maksud - baik dengan gips atau dengan memberikan jalur modul lengkap ). Kadang-kadang, itu bisa mengganggu, tetapi mencegah semua jenis masalah pembajakan fungsi . Anda tahu bahwa Anda benar-benar memanggil fungsi yang Anda maksudkan.
Sistem modul D jauh lebih bersih daripada C ++'s #includes (belum lagi, cara kompilasi yang lebih cepat), tetapi tidak memiliki jenis penamaan apa pun di luar modul itu sendiri. Jadi, jika Anda ingin namespace dalam sebuah modul, Anda harus pergi dengan rute Java dan menggunakan fungsi statis pada kelas atau struct. Ini berfungsi, tetapi jika Anda benar-benar ingin namespacing, itu jelas tidak sebersih namespace nyata. Namun, untuk sebagian besar situasi, penempatan nama yang disediakan oleh modul itu sendiri sangat banyak (dan sebenarnya cukup canggih dalam hal-hal seperti konflik sebenarnya).
Seperti Java dan C #, D memiliki pewarisan tunggal daripada pewarisan berganda, tetapi tidak seperti Java dan C #, D memberi Anda beberapa cara fantastis untuk mendapatkan efek yang sama tanpa semua masalah yang dimiliki pewarisan berganda C ++ (dan pewarisan berganda C ++ dapat menjadi sangat berantakan) kadang-kadang). D tidak hanya memiliki antarmuka , tetapi juga memiliki string mixin , template mixin , dan alias ini . Jadi, hasil akhirnya bisa dikatakan lebih kuat dan tidak memiliki semua masalah yang dimiliki oleh beberapa warisan C ++.
Mirip dengan C #, D memisahkan struct dan kelas . Kelas adalah tipe referensi yang memiliki pewarisan dan diturunkan
Object
, sedangkan struct adalah tipe nilai tanpa pewarisan. Pemisahan ini bisa baik dan buruk. Ini menghilangkan masalah slicing klasik dalam C ++ dan membantu tipe terpisah yang benar-benar tipe nilai dari yang seharusnya polimorfik, tetapi pada awalnya, setidaknya, perbedaannya mungkin mengganggu bagi programmer C ++. Pada akhirnya, ada sejumlah manfaat untuk itu, tetapi itu memang memaksa Anda untuk berurusan dengan tipe Anda agak berbeda.Anggota fungsi dari kelas yang polimorfik secara default. Anda tidak dapat mendeklarasikannya non-virtual . Terserah kompiler untuk memutuskan apakah mereka bisa (yang benar-benar hanya kasus jika mereka final dan tidak mengesampingkan fungsi dari kelas dasar). Jadi, itu bisa menjadi masalah kinerja dalam beberapa kasus. Namun, jika Anda benar-benar tidak memerlukan polimorfisme, maka yang harus Anda lakukan adalah menggunakan struct , dan itu bukan masalah.
D memiliki pengumpul sampah bawaan . Banyak dari C ++ akan menganggap itu sebagai kerugian serius, dan kebenarannya, saat ini, implementasinya dapat menggunakan beberapa pekerjaan serius. Sudah membaik, tapi jelas tidak sebanding dengan pengumpul sampah Jawa. Namun, ini dimitigasi oleh dua faktor. Pertama, jika Anda terutama menggunakan struct dan tipe data lain di stack, maka itu bukan masalah besar. Jika program Anda tidak terus mengalokasikan dan menghapuskan hal-hal di heap, itu akan baik-baik saja. Dan dua, Anda dapat melewati pengumpul sampah jika Anda mau dan cukup menggunakan C's
malloc
danfree
. Ada beberapa fitur bahasa (seperti irisan array) yang harus Anda hindari atau berhati-hati, dan beberapa pustaka standar tidak benar-benar dapat digunakan tanpa setidaknya beberapa penggunaan GC (terutama pemrosesan string), tetapi Anda dapat menulis dalam D tanpa menggunakan pengumpul sampah jika kamu benar-benar ingin. Hal yang cerdas untuk dilakukan adalah mungkin menggunakannya secara umum dan kemudian menghindarinya ketika profil menunjukkan bahwa itu menyebabkan masalah untuk kode kinerja kritis, tetapi Anda dapat menghindarinya sepenuhnya jika Anda mau. Dan kualitas implementasi GC akan meningkat dari waktu ke waktu, menghilangkan banyak kekhawatiran yang mungkin menyebabkan penggunaan GC . Jadi, pada akhirnya, GC tidak akan menjadi masalah besar, dan tidak seperti Java, Anda dapat menghindarinya jika Anda mau.Mungkin ada yang lain juga, tapi itulah yang bisa saya pikirkan saat ini. Dan jika Anda akan melihat, mereka semua adalah pengorbanan. D memilih untuk melakukan beberapa hal secara berbeda dari C ++ yang memiliki keunggulan pasti atas bagaimana C ++ melakukannya tetapi juga memiliki beberapa kelemahan. Yang lebih baik tergantung pada apa yang Anda lakukan, dan dalam banyak kasus mungkin hanya akan tampak lebih buruk pada awalnya dan kemudian Anda tidak akan memiliki masalah dengan itu setelah Anda terbiasa. Jika ada, masalah dalam D umumnya akan menjadi masalah baru yang disebabkan oleh hal-hal baru yang belum dilakukan bahasa lain sebelumnya atau belum dilakukan dengan cara yang sama seperti yang dimiliki D. Secara keseluruhan, D telah belajar dengan baik dari kesalahan C ++.
Dan D, sebagai bahasa, meningkat lebih dari C ++ dalam banyak hal yang saya pikir umumnya D lebih baik secara objektif.
D memiliki kompilasi bersyarat . Ini adalah salah satu fitur yang sering saya lewatkan ketika saya pemrograman di C ++. Jika C ++ akan menambahkannya, maka C ++ akan meningkat dengan pesat ketika datang ke hal-hal seperti template.
D memiliki refleksi waktu kompilasi .
Variabel adalah thread-local secara default tetapi bisa
shared
jika Anda menginginkannya. Ini membuat berurusan dengan utas jauh lebih bersih daripada di C ++. Anda memegang kendali penuh. Anda dapat menggunakanimmutable
dan menyampaikan pesan untuk berkomunikasi antara utas, atau Anda dapat membuat variabelshared
dan melakukannya dengan cara C ++ dengan mutex dan variabel kondisi. Bahkan itu ditingkatkan dari C ++ dengan pengenalan yang disinkronkan (mirip dengan C # dan Java). Jadi, situasi threading D jauh lebih baik daripada C ++.Template D jauh lebih kuat daripada template C ++, memungkinkan Anda untuk melakukan jauh lebih banyak, jauh lebih mudah. Dan dengan penambahan batasan template, pesan kesalahan jauh lebih baik daripada di C ++. D membuat templat sangat kuat dan bermanfaat. Bukan kebetulan bahwa penulis Modern C ++ Design adalah salah satu kolaborator utama D. Saya menemukan template C ++ kurang serius dibandingkan dengan template D, dan itu bisa sangat membuat frustasi saat pemrograman di C ++.
D memiliki pemrograman kontrak bawaan .
D memiliki kerangka uji unit bawaan.
D memiliki dukungan bawaan untuk unicode dengan
string
(UTF-8),wstring
(UTF-16), dandstring
(UTF-32). Itu membuatnya mudah untuk berurusan dengan unicode. Dan jika Anda hanya ingin menggunakanstring
dan umumnya tidak khawatir tentang unicode, Anda dapat - meskipun beberapa pemahaman tentang dasar-dasar unicode membantu dengan beberapa fungsi perpustakaan standar.Overloading operator D jauh lebih baik daripada C ++, memungkinkan Anda untuk menggunakan satu fungsi untuk membebani banyak operator secara bersamaan. Contoh utama dari ini adalah ketika Anda perlu membebani operator aritmatika dasar dan implementasinya sama kecuali untuk operator. Mixin string membuatnya mudah, memungkinkan Anda untuk memiliki satu, definisi fungsi sederhana untuk semuanya.
Array D jauh lebih baik daripada array C ++. Tidak hanya mereka jenis yang tepat dengan panjang, tetapi mereka dapat ditambahkan dan diubah ukurannya. Menggabungkannya mudah. Dan yang terbaik, mereka memiliki irisan . Dan itu adalah anugerah besar untuk pemrosesan array yang efisien. String adalah array karakter dalam D, dan itu bukan masalah (sebenarnya itu hebat!), Karena array D sangat kuat.
Saya bisa terus dan terus. Banyak perbaikan yang diberikan D adalah hal-hal kecil (seperti menggunakan
this
untuk nama konstruktor atau melarang jika pernyataan atau loop body di mana tanda titik koma adalah seluruh tubuh mereka), tetapi beberapa dari mereka cukup besar, dan ketika Anda menambahkan semuanya, itu membuat pengalaman pemrograman yang jauh lebih baik. C ++ 0x memang menambahkan beberapa fitur yang D miliki dimana C ++ tidak ada (mis.auto
Dan lambdas), tetapi bahkan dengan semua perbaikannya, masih tidak banyak yang secara objektif lebih baik tentang C ++ sebagai bahasa daripada D.Tidak ada pertanyaan bahwa ada banyak alasan subyektif untuk menyukai satu sama lain, dan ketidakmatangan relatif dari implementasi D dapat menjadi masalah pada waktu (meskipun telah meningkat sangat cepat akhir-akhir ini - terutama karena repositori dipindahkan ke github ) , dan kurangnya perpustakaan pihak ke-3 pasti bisa menjadi masalah (meskipun fakta bahwa D dapat dengan mudah memanggil fungsi C - dan pada tingkat lebih rendah, fungsi C ++ - pasti mengurangi masalah). Tapi itu adalah kualitas masalah implementasi daripada masalah dengan bahasa itu sendiri. Dan ketika kualitas masalah implementasi diperbaiki, akan jauh lebih menyenangkan untuk menggunakan D.
Jadi, saya kira jawaban singkat untuk pertanyaan ini adalah "sangat sedikit." D, sebagai bahasa, umumnya lebih unggul daripada C ++.
sumber
RAII dan susun penggunaan memori
D 2.0 tidak memungkinkan RAII terjadi di stack karena itu menghapus nilai
scope
kata kunci dalam mengalokasikan instance kelas pada stack.Anda tidak dapat melakukan pewarisan tipe nilai dalam D, begitu efektif sehingga memaksa Anda untuk melakukan alokasi tumpukan untuk segala bentuk RAII.
Yaitu, kecuali Anda menggunakan
emplace
, tetapi itu sangat menyakitkan untuk digunakan, karena Anda harus mengalokasikan memori dengan tangan. (Saya belum menemukannya praktis untuk digunakanemplace
dalam D.)sumber
C ++ jauh lebih baik dalam memaksa Anda untuk menjadi verbose. Ini mungkin lebih baik atau lebih buruk di mata Anda, tergantung pada apakah Anda suka inferensi atau kata-kata.
Bandingkan memoisasi run-time di C ++ :
dengan hal yang sama di D:
Perhatikan, misalnya, verbositas ekstra dengan
template <typename ReturnType, typename... Args>
versus(F)
,Args...
versusArgs
,args...
versusargs
, dll.Untuk lebih baik atau lebih buruk, C ++ lebih bertele-tele.
Tentu saja, Anda juga bisa melakukan ini dalam D:
dan mereka akan terlihat hampir sama, tetapi kemudian ini akan membutuhkan
delegate
, sedangkan aslinya diterima setiap objek callable. (Versi C ++ 0x membutuhkanstd::function
objek, jadi bagaimanapun juga, itu lebih verbose dan restriktif dalam inputnya ... yang bisa bagus jika Anda suka verbosity, buruk jika Anda tidak.)sumber
Saya tidak tahu banyak tentang D, tetapi banyak, banyak programmer C ++ yang saya tahu sangat tidak menyukainya, dan saya pribadi harus setuju - Saya tidak suka tampilan D dan tidak akan mengambil yang lebih dekat.
Untuk memahami mengapa D tidak mendapatkan daya tarik lebih, Anda harus mulai dengan memahami apa yang menarik orang ke C ++. Singkatnya, alasan nomor satu adalah kontrol. Ketika Anda memprogram dalam C ++, maka Anda memiliki kontrol penuh atas program Anda. Ingin mengganti perpustakaan Standar? Kamu bisa. Ingin melakukan cast pointer yang tidak aman? Kamu bisa. Ingin melanggar const-correctness? Kamu bisa. Ingin mengganti pengalokasi memori? Kamu bisa. Ingin menyalin sekitar memori mentah tanpa memperhatikan jenisnya? Jika Anda benar-benar mau. Ingin mewarisi dari banyak implementasi? Ini pemakamanmu. Sial, Anda bahkan bisa mendapatkan perpustakaan pengumpulan sampah, seperti kolektor Boehm. Kemudian Anda memiliki masalah seperti kinerja, yang erat mengikuti kontrol - semakin banyak kontrol yang dimiliki programmer, semakin optimal ia dapat membuat programnya.
Berikut adalah beberapa hal yang saya lihat ketika melakukan sedikit riset dan berbicara kepada beberapa orang yang telah mencobanya:
Jenis hierarki terpadu. Pengguna C ++ jarang menggunakan pewarisan, sebagian besar programmer C ++ lebih suka komposisi, dan tipe hanya boleh dihubungkan melalui pewarisan jika ada alasan yang sangat bagus untuk melakukannya. Konsep Obyek sangat melanggar prinsip ini dengan menghubungkan setiap tipe. Selain itu, itu melanggar salah satu prinsip paling dasar C ++ - Anda hanya menggunakan apa yang Anda inginkan. Tidak diberi pilihan tentang mewarisi dari Object, dan biaya yang menyertainya, sangat kuat terhadap apa C + + berdiri sebagai bahasa dalam hal memberikan kontrol programmer atas programnya.
Saya pernah mendengar tentang masalah dengan fungsi dan delegasi. Rupanya, D memiliki kedua fungsi dan delegasi sebagai tipe fungsi runable-time yang dapat dipanggil, dan keduanya tidak sama tetapi keduanya dapat dipertukarkan atau ... sesuatu? Teman saya punya beberapa masalah dengan mereka. Ini jelas merupakan penurunan versi dari C ++, yang baru saja
std::function
dilakukan dan Anda selesai.Maka Anda punya kompatibilitas. D tidak terlalu kompatibel dengan C ++. Maksud saya, tidak ada bahasa yang kompatibel dengan C ++, mari kita hadapi itu, kecuali C ++ / CLI yang agak curang, tetapi sebagai penghalang untuk masuk, harus disebutkan.
Lalu, ada beberapa hal lainnya. Misalnya, baca saja entri Wikipedia.
printf
adalah salah satu fungsi paling tidak aman yang pernah dibuat, dalam keluarga yang sama dengan masalah besar sepertigets
dari perpustakaan C Standard lama. Jika Anda mencarinya di Stack Overflow, Anda akan menemukan banyak, banyak pertanyaan yang berkaitan dengan penyalahgunaannya. Pada dasarnya,printf
ini adalah pelanggaran KERING- Anda memberikan tipe dalam string format, dan kemudian memberikannya lagi saat Anda memberikan argumen. Pelanggaran KERING di mana jika Anda salah, maka hal-hal yang sangat buruk terjadi- katakanlah, jika Anda mengubah typedef dari bilangan bulat 16-bit menjadi 32-bit. Ini juga tidak dapat diperpanjang sama sekali- bayangkan apa yang akan terjadi jika semua orang menemukan penentu format mereka sendiri. Iostreams C ++ mungkin lambat, dan pilihan operator mereka mungkin bukan yang terbesar, dan antarmuka mereka bisa menggunakan pekerjaan, tetapi mereka pada dasarnya dijamin aman, dan KERING tidak dilanggar, dan mereka dapat dengan mudah diperpanjang. Ini bukan sesuatu yang bisa dikatakanprintf
.Tidak ada pewarisan berganda. Itu sangat bukan cara C ++. Pemrogram C ++ berharap memiliki kendali penuh atas program mereka dan bahasa yang menegakkan apa yang tidak dapat Anda warisi merupakan pelanggaran terhadap prinsip itu. Selain itu, itu membuat warisan (bahkan lebih) rapuh, karena jika Anda mengubah jenis dari antarmuka ke kelas karena Anda ingin memberikan implementasi default atau sesuatu, tiba-tiba semua kode pengguna Anda rusak. Itu bukan hal yang baik.
Contoh lain adalah
string
danwstring
. Dalam C ++ sudah cukup menyakitkan untuk harus mengkonversi di antara mereka, dan apakah pustaka ini mendukung Unicode, dan pustaka C lama ini hanya menggunakanconst char*
, dan harus menulis versi berbeda dari fungsi yang sama tergantung pada tipe argumen string yang Anda inginkan. Khususnya, tajuk Windows, misalnya, memiliki beberapa makro yang sangat menjengkelkan untuk mengatasi masalah yang sering dapat mengganggu kode Anda sendiri. Menambahkandstring
ke campuran hanya akan membuat segalanya lebih buruk, karena sekarang alih-alih dua jenis string, Anda harus mengelola tiga. Memiliki lebih dari satu tipe string akan meningkatkan rasa sakit pemeliharaan dan memperkenalkan kode berulang yang berurusan dengan string.Scott Meyers menulis:
Isolasi thread yang didukung bahasa bukan merupakan nilai tambah. Pemrogram C ++ mengharapkan kontrol penuh atas program mereka, dan bahasa yang memaksa sesuatu jelas bukan yang diperintahkan dokter.
Saya juga akan menyebutkan manipulasi string waktu kompilasi. D memiliki kemampuan untuk menafsirkan kode D pada waktu kompilasi. Ini bukan nilai tambah. Pertimbangkan sakit kepala masif yang disebabkan oleh preprosesor C yang relatif terbatas, yang terkenal oleh semua programmer veteran C ++, dan kemudian bayangkan betapa buruknya fitur ini akan disalahgunakan. Kemampuan untuk membuat kode D pada waktu kompilasi sangat bagus, tetapi harus semantik , bukan sintaksis.
Selain itu, Anda dapat mengharapkan refleks tertentu. D memiliki koleksi sampah, yang akan diasosiasikan oleh para programmer C ++ dengan bahasa-bahasa seperti Java dan C # yang secara langsung menentangnya dalam filosofi, dan persamaan sintaksis juga akan mengingatkan mereka. Ini belum tentu dibenarkan secara objektif, tetapi itu adalah sesuatu yang tentu harus dicatat.
Pada dasarnya, ia tidak menawarkan banyak yang tidak bisa dilakukan oleh programmer C ++. Mungkin lebih mudah untuk menulis metaprogram faktorial dalam D, tetapi kita sudah dapat menulis metaprogram faktorial dalam C ++. Mungkin dalam D Anda dapat menulis pelacak ray waktu kompilasi, tetapi tidak ada yang benar-benar ingin melakukannya. Dibandingkan dengan pelanggaran mendasar filsafat C ++, apa yang dapat Anda lakukan dalam D tidak terlalu menonjol.
Bahkan jika hal-hal ini hanya masalah di permukaan, maka saya cukup yakin bahwa fakta bahwa di permukaan, D sebenarnya tidak terlihat seperti C ++ sama sekali mungkin merupakan alasan yang baik bahwa banyak programmer C ++ tidak bermigrasi ke D. Mungkin D perlu melakukan iklan pekerjaan yang lebih baik.
sumber
std::function
dilakukan dan Anda selesai. Mengapa? Karena Anda juga, misalnya, memiliki pointer fungsi. Ini persis hal yang sama di "fungsi" D: D adalah pointer fungsi, dan "delegasi" D sama dengan C ++std::function
(kecuali bahwa mereka built-in). Tidak ada "downgrade" di mana pun - dan ada korespondensi 1: 1 di antara mereka, jadi sama sekali tidak membingungkan jika Anda terbiasa dengan C ++.Satu hal yang saya hargai dalam C ++ adalah kemampuan untuk mendokumentasikan argumen fungsi atau mengembalikan nilai sebagai referensi C ++ alih-alih sebuah pointer, karenanya menyiratkan mengambil
null
nilai yang tidak bernilai.Versi D:
Versi C ++:
Agar adil Anda bisa menjadi sangat dekat dengan C ++ dengan membuat
A
menjadi Dstruct
dan menandaifoo()
-argumen sebagai aref
(kelas adalah tipe referensi dan struct adalah tipe nilai dalam D, mirip dengan C #).Saya percaya ada rencana untuk membuat
NonNullable
templat untuk kelas sebagai konstruksi pustaka standar D sebagai gantinya. Meski begitu saya suka singkatnya hanyaType&
dibandingkan denganNonNullable(Type)
, dan akan lebih memilih non-nullable sebagai default (rendering sesuatu sepertiType
danNullable(Type)
). Tapi sudah terlambat untuk mengubah itu untuk D dan saya keluar topik sekarang.sumber
ref
untuk memberi Anda efek yang sama dengan C ++&
. Satu perbedaan utama adalah bahwa halref
itu tidak akan berlangsung sementara meskipun ituconst
.Hal yang paling penting bahwa C ++ "lebih baik" daripada D adalah berinteraksi dengan perpustakaan lama . Berbagai mesin 3D, OpenCL dan sejenisnya. Karena D adalah baru, ia memiliki jumlah perpustakaan berbeda yang jauh lebih kecil untuk dipilih.
Perbedaan penting lainnya antara C ++ dan D adalah bahwa C ++ memiliki banyak vendor independen secara finansial, tetapi pada 2014 D secara praktis hanya memiliki satu , tim 2 orang yang menciptakannya. Sangat menarik bahwa "prinsip sumber kedua" yang mengatakan bahwa proyek tidak boleh bergantung pada teknologi, komponen, yang hanya memiliki satu, tunggal, vendor, tampaknya berlaku bahkan untuk perangkat lunak.
Sebagai perbandingan, versi pertama dari interpreter Ruby ditulis oleh penemu Ruby, Yukihiro Matsumoto, tetapi juru bahasa Ruby mainstream era 2014 telah ditulis secara praktis dari awal oleh orang lain. Oleh karena itu, Ruby dapat dilihat sebagai bahasa yang memiliki lebih dari satu vendor yang mandiri secara finansial. D, di sisi lain, bisa menjadi teknologi yang luar biasa, tetapi itu tergantung pada beberapa pengembang yang mengembangkannya.
Sejarah Jawa menunjukkan bahwa bahkan jika suatu teknologi, dalam hal ini, Jawa, memiliki pemodal yang bagus, tetapi tunggal, ada risiko besar bahwa teknologi tersebut pada dasarnya dibuang, terlepas dari basis pengguna korporat yang besar. Kutipan dari Yayasan Perangkat Lunak Apache , di mana Komisi Eropa mewakili "Komite Eksekutif":
Oracle menyediakan EC dengan permintaan spesifikasi Java SE 7 dan lisensi yang saling bertentangan, sangat membatasi distribusi implementasi independen dari spesifikasi, dan yang paling penting, melarang distribusi implementasi open source independen dari spesifikasi.
Sebagai catatan sejarah, dapat dikatakan bahwa applet Java memiliki perangkat keras yang dipercepat kanvas 3D bertahun-tahun sebelum WebGL HTML5 dikembangkan. Masalah kecepatan awal applet Java dapat dipecahkan, jika Java merupakan proyek komunitas, tetapi eksekutif satu-satunya pemodal Java, Sun Microsystems, tidak merasa cukup penting untuk memperbaiki implementasi Java. Hasil akhirnya: kanvas HTML5 oleh beberapa vendor sebagai "replika orang miskin" dari kerangka kerja Java GUI (Swing, dll.). Yang cukup menarik, di sisi server bahasa pemrograman Python memiliki kelebihan yang sama seperti yang dijanjikan Java: menulis sekali, berjalan di setiap server, terlepas dari perangkat kerasnya, asalkan aplikasi Python tidak dikompilasi ke kode mesin. Python adalah tentang tua / muda seperti Jawa, tetapi tidak seperti Java, itu '
Ringkasan:
Ketika mengevaluasi teknologi untuk penggunaan produksi, sifat paling penting dari teknologi adalah orang-orang, yang mengembangkannya, proses sosial, di mana pengembangan berlangsung, dan jumlah tim pengembangan yang mandiri secara finansial.
Apakah lebih menguntungkan menggunakan teknologi T1 daripada teknologi T2 tergantung pada vendor teknologi dan apakah teknologi T1 memungkinkan untuk menyelesaikan masalah terkait proyek lebih murah daripada T2. Misalnya, jika masalah pemasok tunggal diabaikan, maka untuk sistem informasi Java akan menjadi teknologi "lebih baik" daripada C ++, karena binari Java tidak perlu dikompilasi ulang saat pemasangan perangkat keras baru dan jumlah pekerjaan pengembangan perangkat lunak terkait manajemen memori lebih kecil untuk Java daripada untuk C ++. Proyek yang dikembangkan dari awal, misalnya proyek yang tidak bergantung pada perpustakaan lain, mungkin lebih murah untuk dikembangkan di D daripada C ++, tetapi, di sisi lain, C ++ memiliki lebih dari satu vendor dan karenanya kurang berisiko dalam jangka panjang . (Contoh Java, di mana Sun Microsystems hampir OK,
Solusi yang Mungkin untuk beberapa Keterbatasan C ++
Salah satu solusi yang mungkin untuk beberapa keterbatasan C ++ adalah dengan menggunakan pola desain, di mana tugas awal diambil berkeping-keping dan potongan-potongan itu "diurutkan" (diklasifikasikan, dikelompokkan, dibagi, kata-kata bagus-lain untuk- the-same-thing) ke 2 kelas: mengontrol tugas-tugas terkait logika , di mana pola akses memori tidak memungkinkan lokalitas; tugas seperti pemrosesan sinyal , di mana lokalitas mudah dicapai. Tugas pemrosesan "suka" sinyal dapat diimplementasikan sebagai satu set program konsol yang relatif sederhana. Tugas terkait kontrol logika ditempatkan semua ke satu skrip yang ditulis dalam Ruby atau Python atau yang lainnya, di mana kenyamanan pengembangan perangkat lunak memiliki prioritas lebih tinggi daripada kecepatan.
Untuk menghindari inisialisasi proses sistem operasi yang mahal dan penyalinan data antara proses sistem operasi, rangkaian aplikasi konsol C ++ kecil dapat diimplementasikan sebagai program C ++ tunggal yang di-boot sebagai "servlet" oleh Ruby / Python / etc. naskah. Ruby / Python / etc. script mematikan servlet sebelum keluar. Komunikasi antara "servlet" dan Ruby / Python / etc. skrip berlangsung di atas pipa bernama Linux atau mekanisme serupa.
Jika tugas awal tidak memungkinkan dirinya untuk dengan mudah dibagi menjadi beberapa bagian yang dapat diklasifikasikan ke dalam 2 kelas yang disebutkan di atas, maka hal yang harus dicoba mungkin adalah mengutarakan kembali masalah sehingga tugas awal berubah.
sumber