Mari kita perhatikan contoh halo dunia berikut dalam C dan C ++:
#include <stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
#include <iostream>
int main()
{
std::cout<<"Hello world"<<std::endl;
return 0;
}
Ketika saya mengkompilasi mereka di godbolt ke assembly, ukuran kode C hanya 9 baris ( gcc -O3
):
.LC0:
.string "Hello world"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
xor eax, eax
add rsp, 8
ret
Tetapi ukuran kode C ++ adalah 22 baris ( g++ -O3
):
.LC0:
.string "Hello world"
main:
sub rsp, 8
mov edx, 11
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
xor eax, eax
add rsp, 8
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:_ZStL8__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZStL8__ioinit
mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
add rsp, 8
jmp __cxa_atexit
... yang jauh lebih besar.
Sangat terkenal bahwa di C ++ Anda membayar untuk apa yang Anda makan. Jadi, dalam hal ini, apa yang saya bayar?
eat
terkait dengan C ++. Saya percaya maksud Anda: "Anda hanya membayar untuk apa yang Anda gunakan "?eat
itu lebih ambigu dan harus dihindari.Jawaban:
Apa yang Anda bayar adalah untuk memanggil perpustakaan yang berat (tidak seberat mencetak ke konsol). Anda menginisialisasi
ostream
objek. Ada beberapa penyimpanan tersembunyi. Kemudian, Anda meneleponstd::endl
yang bukan sinonim untuk\n
. Theiostream
perpustakaan membantu Anda menyesuaikan banyak pengaturan dan menempatkan beban pada prosesor daripada programmer. Ini yang Anda bayar.Mari kita tinjau kodenya:
Menginisialisasi objek oout + cout
Memanggil
cout
lagi untuk mencetak baris baru dan menyiramInisialisasi penyimpanan statis:
Juga, penting untuk membedakan antara bahasa dan perpustakaan.
BTW, ini hanya sebagian dari cerita. Anda tidak tahu apa yang tertulis dalam fungsi yang Anda panggil.
sumber
cout; printf; cout
menulis secara berurutan (Karena mereka memiliki buffer sendiri). Yang kedua akan melakukan sinkronisasicout
dancin
, menyebabkancout; cin
berpotensi meminta pengguna untuk informasi terlebih dahulu. Pembilasan akan memaksanya untuk melakukan sinkronisasi hanya ketika Anda benar-benar membutuhkannya.std::cout
lebih kuat dan rumit daripadaprintf
. Ini mendukung hal-hal seperti locales, flag format stateful, dan banyak lagi.Jika Anda tidak membutuhkannya, gunakan
std::printf
ataustd::puts
- tersedia<cstdio>
.Saya juga ingin memperjelas bahwa C ++ ! = The C ++ Standard Library. Perpustakaan Standar seharusnya bertujuan umum dan "cukup cepat", tetapi seringkali lebih lambat daripada implementasi khusus dari apa yang Anda butuhkan.
Di sisi lain, bahasa C ++ berusaha untuk memungkinkan untuk menulis kode tanpa membayar biaya tersembunyi tambahan yang tidak perlu (misalnya memilih ikut
virtual
, tidak ada pengumpulan sampah).sumber
Anda tidak membandingkan C dan C ++. Anda membandingkan
printf
danstd::cout
, yang mampu melakukan berbagai hal (lokal, format stateful, dll).Coba gunakan kode berikut untuk perbandingan. Godbolt menghasilkan rakitan yang sama untuk kedua file (diuji dengan gcc 8.2, -O3).
main.c:
main.cpp:
sumber
Daftar Anda memang membandingkan apel dan jeruk, tetapi bukan karena alasan yang tersirat dalam sebagian besar jawaban lain.
Mari kita periksa apa kode Anda sebenarnya:
C:
"Hello world\n"
C ++:
"Hello world"
ke dalamstd::cout
std::endl
manipulator kestd::cout
Tampaknya kode C ++ Anda melakukan pekerjaan dua kali lebih banyak. Untuk perbandingan yang adil, kita harus menggabungkan ini:
... dan tiba-tiba kode assembly Anda untuk
main
terlihat sangat mirip dengan C:Bahkan, kita dapat membandingkan kode C dan C ++ baris demi baris, dan ada sedikit perbedaan :
Satu-satunya perbedaan nyata adalah bahwa dalam C ++ kita memanggil
operator <<
dengan dua argumen (std::cout
dan string). Kita dapat menghapus bahkan sedikit perbedaan dengan menggunakan persamaan C yang lebih dekat:,fprintf
yang juga memiliki argumen pertama yang menentukan aliran.Ini meninggalkan kode rakitan
_GLOBAL__sub_I_main
, yang dihasilkan untuk C ++ tetapi bukan C. Ini adalah satu-satunya overhead sebenarnya yang terlihat dalam daftar rakitan ini ( tentu saja , lebih banyak overhead tidak terlihat untuk kedua bahasa). Kode ini melakukan pengaturan satu kali untuk beberapa fungsi pustaka standar C ++ pada awal program C ++.Tetapi, seperti dijelaskan dalam jawaban lain, perbedaan yang relevan antara kedua program ini tidak akan ditemukan dalam output perakitan
main
fungsi karena semua pengangkatan berat terjadi di belakang layar.sumber
_start
tetapi kodenya adalah bagian dari pustaka runtime C. Bagaimanapun ini terjadi untuk C dan C ++.std::cout
dan bukannya lewat I / O untuk pelaksanaan stdio (yang menggunakan mekanisme buffer sendiri). Secara khusus, ketika terhubung ke (apa yang dikenal sebagai) terminal interaktif, maka secara default Anda tidak akan pernah melihat output buffered sepenuhnya saat menulisstd::cout
. Anda harus secara eksplisit menonaktifkan sinkronisasi dengan stdio jika Anda ingin pustaka iostream menggunakan mekanisme bufferingnya sendiristd::cout
.printf
tidak perlu menyiram aliran di sini. Bahkan, dalam kasus penggunaan umum (output diarahkan ke file), Anda biasanya akan menemukan bahwaprintf
pernyataan tidak rata. Hanya ketika output buffer line atau unbuffered akanprintf
memicu flush.Sederhana saja. Anda membayar
std::cout
. "Anda hanya membayar apa yang Anda makan" tidak berarti "Anda selalu mendapatkan harga terbaik". Tentu,printf
lebih murah. Orang bisa membantahnyastd::cout
itu lebih aman dan lebih fleksibel, sehingga biayanya yang lebih besar dapat dibenarkan (harganya lebih banyak, tetapi memberikan nilai lebih), tetapi itu tidak tepat. Anda tidak menggunakanprintf
, Anda menggunakanstd::cout
, jadi Anda membayar untuk menggunakanstd::cout
. Anda tidak membayar untuk menggunakanprintf
.Contoh yang baik adalah fungsi virtual. Fungsi virtual memiliki beberapa biaya runtime dan persyaratan ruang - tetapi hanya jika Anda benar-benar menggunakannya. Jika Anda tidak menggunakan fungsi virtual, Anda tidak membayar apa pun.
Beberapa komentar
Bahkan jika kode C ++ mengevaluasi lebih banyak instruksi perakitan, itu masih sedikit instruksi, dan setiap overhead kinerja masih mungkin dikerdilkan oleh operasi I / O yang sebenarnya.
Sebenarnya, kadang-kadang bahkan lebih baik daripada "di C ++ Anda membayar apa yang Anda makan". Sebagai contoh, kompiler dapat menyimpulkan bahwa panggilan fungsi virtual tidak diperlukan dalam beberapa keadaan, dan mengubahnya menjadi panggilan non-virtual. Itu berarti Anda dapat memperoleh fungsi virtual secara gratis . Bukankah itu hebat?
sumber
"Daftar rakitan untuk printf" BUKAN untuk printf, tetapi untuk put (jenis optimasi kompiler?); printf jauh lebih kompleks daripada menempatkan ... jangan lupa!
sumber
std::cout
internal, yang tidak terlihat dalam daftar perakitan.puts
, yang terlihat sama dengan panggilanprintf
jika Anda hanya melewatkan string format tunggal dan nol argumen tambahan. (Kecuali akan ada jugaxor %eax,%eax
karena kita melewatkan nol argumen FP dalam register ke fungsi variadic.) Tidak satu pun dari ini adalah implementasinya, hanya meneruskan pointer ke string ke fungsi library. Tapi ya, mengoptimalkanprintf
untukputs
sesuatu gcc tidak untuk format yang hanya memiliki"%s"
, atau ketika tidak ada konversi, dan string berakhir dengan baris baru.Saya melihat beberapa jawaban yang valid di sini, tetapi saya akan sedikit lebih detail.
Lompat ke ringkasan di bawah ini untuk menjawab pertanyaan utama Anda jika Anda tidak ingin membaca seluruh dinding teks ini.
Abstraksi
Anda membayar abstraksi . Mampu menulis kode yang lebih sederhana dan lebih ramah manusia datang dengan biaya. Dalam C ++, yang merupakan bahasa berorientasi objek, hampir semuanya adalah objek. Saat Anda menggunakan objek apa pun, tiga hal utama akan selalu terjadi di bawah tenda:
init()
metode). Biasanya alokasi memori terjadi di bawah tenda sebagai hal pertama dalam langkah ini.Anda tidak melihatnya dalam kode, tetapi setiap kali Anda menggunakan objek, ketiga hal di atas perlu terjadi. Jika Anda melakukan semuanya secara manual, kode jelas akan jauh lebih lama.
Sekarang, abstraksi dapat dibuat secara efisien tanpa menambahkan overhead: inlining metode dan teknik lainnya dapat digunakan oleh kompiler dan programmer untuk menghilangkan overhead abstraksi, tetapi ini bukan kasus Anda.
Apa yang sebenarnya terjadi di C ++?
Ini dia, rusak:
std::ios_base
kelas diinisialisasi, yang merupakan kelas dasar untuk semua I / O yang terkait.std::cout
objek diinisialisasi.std::__ostream_insert
, yang (seperti yang sudah Anda ketahui namanya) adalah metodestd::cout
(pada dasarnya<<
operator) yang menambahkan string ke aliran.cout::endl
juga diteruskan kestd::__ostream_insert
.__std_dso_handle
diteruskan ke__cxa_atexit
, yang merupakan fungsi global yang bertanggung jawab untuk "pembersihan" sebelum keluar dari program.__std_dso_handle
sendiri dipanggil oleh fungsi ini untuk mendelokasi dan menghancurkan objek global yang tersisa.Jadi menggunakan C == tidak membayar apa pun?
Dalam kode C, sangat sedikit langkah yang terjadi:
puts
melaluiedi
register.puts
dipanggil.Tidak ada benda di mana pun, maka tidak perlu menginisialisasi / menghancurkan apa pun.
Namun ini tidak berarti bahwa Anda tidak "membayar" untuk apa pun di C . Anda masih membayar abstraksi, dan juga inisialisasi pustaka standar C dan resolusi dinamis
printf
fungsi (atau, sebenarnyaputs
, yang dioptimalkan oleh kompiler karena Anda tidak memerlukan format string) masih terjadi di bawah tenda.Jika Anda menulis program ini dalam perakitan murni, akan terlihat seperti ini:
Yang pada dasarnya hanya menghasilkan memanggil
write
syscall diikuti olehexit
syscall. Sekarang ini akan menjadi minimum untuk mencapai hal yang sama.Untuk meringkas
C adalah cara yang lebih sederhana , dan hanya melakukan minimum yang diperlukan, meninggalkan kontrol penuh kepada pengguna, yang mampu mengoptimalkan dan menyesuaikan sepenuhnya apa pun yang mereka inginkan. Anda memberi tahu prosesor untuk memuat string dalam register dan kemudian memanggil fungsi pustaka untuk menggunakan string itu. C ++ di sisi lain jauh lebih kompleks dan abstrak . Ini memiliki keuntungan yang sangat besar ketika menulis kode yang rumit, dan memungkinkan untuk lebih mudah untuk menulis dan kode yang lebih ramah manusia, tetapi jelas ada biaya. Akan selalu ada kelemahan dalam kinerja di C ++ jika dibandingkan dengan C dalam kasus-kasus seperti ini, karena C ++ menawarkan lebih dari apa yang dibutuhkan untuk menyelesaikan tugas-tugas dasar seperti itu, dan dengan demikian menambah lebih banyak overhead .
Menjawab pertanyaan utama Anda :
Dalam kasus khusus ini, ya . Anda tidak mengambil keuntungan dari apa pun yang ditawarkan oleh C ++ lebih dari C, tetapi itu hanya karena tidak ada apa pun dalam potongan kode sederhana yang dapat membantu C ++: sangat sederhana sehingga Anda benar-benar tidak memerlukan C ++ sama sekali.
Oh, dan satu hal lagi!
Kelebihan C ++ mungkin tidak terlihat jelas pada pandangan pertama, karena Anda menulis sebuah program yang sangat sederhana dan kecil, tetapi lihatlah contoh yang sedikit lebih kompleks dan lihat perbedaannya (kedua program melakukan hal yang persis sama):
C :
C ++ :
Semoga Anda bisa melihat dengan jelas apa yang saya maksud di sini. Juga perhatikan bagaimana dalam C Anda harus mengelola memori pada tingkat yang lebih rendah menggunakan
malloc
danfree
bagaimana Anda harus lebih berhati-hati tentang pengindeksan dan ukuran, dan bagaimana Anda harus sangat spesifik saat mengambil input dan mencetak.sumber
Ada beberapa kesalahpahaman untuk memulai. Pertama, program C ++ tidak menghasilkan 22 instruksi, ini lebih seperti 22.000 dari mereka (saya menarik nomor itu dari topi saya, tetapi kira-kira di stadion baseball itu). Juga, kode C. tidak menghasilkan 9 instruksi, baik. Hanya itu yang Anda lihat.
Apa yang dilakukan kode C adalah, setelah melakukan banyak hal yang tidak Anda lihat, ia memanggil fungsi dari CRT (yang biasanya tetapi tidak harus hadir sebagai shared lib), kemudian tidak memeriksa nilai pengembalian atau menangani kesalahan, dan uang jaminan. Tergantung pada kompiler dan pengaturan optimasi itu bahkan tidak benar-benar memanggil
printf
tetapiputs
, atau sesuatu yang lebih primitif.Anda bisa menulis kurang lebih program yang sama (kecuali untuk beberapa fungsi init yang tak terlihat) di C ++ juga, jika saja Anda memanggil fungsi yang sama dengan cara yang sama. Atau, jika Anda ingin super-benar, fungsi yang sama diawali dengan
std::
.Kode C ++ yang sesuai pada kenyataannya tidak semuanya sama. Meskipun keseluruhannya
<iostream>
terkenal sebagai babi jelek yang gemuk yang menambahkan biaya overhead yang besar untuk program kecil (dalam program "nyata" Anda tidak terlalu memperhatikannya), interpretasi yang agak lebih adil adalah bahwa ia melakukan hal yang buruk. banyak hal yang tidak Anda lihat dan yang berfungsi . Termasuk tetapi tidak terbatas pada pemformatan magis dari hampir semua barang sembarangan, termasuk berbagai format angka dan lokal dan yang lainnya, dan buffering, dan penanganan kesalahan yang tepat. Menangani kesalahan? Ya, coba tebak, mengeluarkan string sebenarnya bisa gagal, dan tidak seperti program C, program C ++ akan melakukannya tidak mengabaikan ini diam-diam. Mempertimbangkan apastd::ostream
tidak di bawah tenda, dan tanpa ada yang tahu, itu sebenarnya cukup ringan. Tidak seperti saya menggunakannya karena saya benci aliran sintaksis dengan penuh gairah. Tapi tetap saja, itu luar biasa jika Anda mempertimbangkan apa yang dilakukannya.Tapi tentu saja, C ++ secara keseluruhan tidak seefisien C dapat. Itu tidak bisa seefisien karena itu bukan hal yang sama dan tidak melakukan hal yang sama. Jika tidak ada yang lain, C ++ menghasilkan pengecualian (dan kode untuk menghasilkan, menangani, atau gagal pada mereka) dan itu memberikan beberapa jaminan bahwa C tidak memberikan. Jadi, tentu saja, program C ++ perlu sedikit lebih besar. Namun, dalam gambaran besar, ini tidak masalah sama sekali. Sebaliknya, untuk program nyata , saya jarang menemukan C ++ berkinerja lebih baik karena untuk satu dan lain alasan, tampaknya memberikan optimisasi yang lebih baik. Jangan tanya kenapa, khususnya, saya tidak akan tahu.
Jika, alih-alih api-dan-lupakan-harapan-untuk-yang terbaik Anda peduli untuk menulis kode C yang benar (yaitu Anda benar-benar memeriksa kesalahan, dan program berperilaku dengan benar di hadapan kesalahan) maka perbedaannya adalah marjinal, jika ada.
sumber
std::cout
pengecualian juga?std::cout
adalah astd::basic_ostream
dan yang dapat dilempar, dan itu dapat mengkaji kembali pengecualian yang terjadi jika dikonfigurasi untuk melakukannya atau ia dapat menelan pengecualian. Masalahnya, hal - hal dapat gagal, dan C ++ serta lib standar C ++ (kebanyakan) dibangun sehingga kegagalan tidak mudah luput dari perhatian. Ini adalah gangguan dan berkah (tapi, lebih banyak berkah dari gangguan). C di sisi lain hanya menunjukkan jari tengah Anda. Anda tidak memeriksa kode kembali, Anda tidak pernah tahu apa yang terjadi.Anda membayar kesalahan. Pada tahun 80-an, ketika kompiler tidak cukup baik untuk memeriksa string format, overloading operator dipandang sebagai cara yang baik untuk menegakkan kemiripan keamanan jenis selama io. Namun, setiap fitur spanduknya diimplementasikan dengan buruk atau secara konsep bangkrut sejak awal:
<iomanip>
Bagian yang paling menjijikkan dari C ++ stream io api adalah keberadaan pustaka header pemformatan ini. Selain stateful dan jelek dan rentan kesalahan, itu pasangan diformat ke aliran.
Misalkan Anda ingin mencetak garis dengan 8 digit nol diisi hex unsigned int diikuti oleh spasi diikuti oleh ganda dengan 3 tempat desimal. Dengan
<cstdio>
, Anda bisa membaca string format ringkas. Dengan<ostream>
, Anda harus menyimpan status lama, atur perataan ke kanan, atur karakter isian, atur lebar isian, atur basis ke hex, output integer, kembalikan keadaan tersimpan (jika tidak, format integer Anda akan mencemari format float Anda), mengeluarkan ruang , atur notasi untuk diperbaiki, atur presisi, output ganda dan baris baru, lalu kembalikan format lama.Operator Kelebihan
<iostream>
adalah anak poster tentang bagaimana tidak menggunakan kelebihan operator:Performa
std::cout
beberapa kali lebih lambatprintf()
. Merebaknya radang usus dan pengiriman maya memang memakan korban.Keamanan Thread
Keduanya
<cstdio>
dan<iostream>
aman dalam setiap fungsi panggilan adalah atom. Tapi,printf()
lebih banyak dilakukan per panggilan. Jika Anda menjalankan program berikut dengan<cstdio>
opsi, Anda hanya akan melihat deretanf
. Jika Anda menggunakan<iostream>
mesin multicore, kemungkinan Anda akan melihat sesuatu yang lain.Retort untuk contoh ini adalah bahwa kebanyakan orang menjalankan disiplin untuk tidak pernah menulis ke deskriptor file tunggal dari beberapa utas. Nah, dalam hal ini, Anda harus mengamati bahwa
<iostream>
akan membantu mengambil kunci pada setiap<<
dan setiap>>
. Sedangkan di<cstdio>
, Anda tidak akan sering mengunci, dan Anda bahkan memiliki pilihan untuk tidak mengunci.<iostream>
mengeluarkan lebih banyak kunci untuk mencapai hasil yang kurang konsisten.sumber
std::cout
Beberapa kali lebih lambatprintf()
” - Klaim ini diulangi di seluruh internet tetapi tidak berlaku lama. Implementasi IOstream modern berfungsi setaraprintf
. Yang terakhir ini juga melakukan pengiriman virtual secara internal untuk menangani buffered stream dan IO terlokalisasi (dilakukan oleh sistem operasi tetapi tetap dilakukan).printf
dancout
menyusut. Kebetulan ada banyak tolok ukur seperti itu di situs ini.Selain apa semua jawaban yang lain telah mengatakan,
ada juga fakta bahwa
std::endl
adalah tidak sama dengan'\n'
.Sayangnya ini adalah kesalahpahaman umum.
std::endl
tidak berarti "baris baru",itu berarti "cetak baris baru dan kemudian siram aliran ". Pembilasan tidak murah!
Sepenuhnya mengabaikan perbedaan antara
printf
danstd::cout
untuk sesaat, agar secara fungsional setara dengan contoh C Anda, contoh C ++ Anda seharusnya terlihat seperti ini:Dan inilah contoh bagaimana seharusnya contoh Anda jika Anda termasuk pembilasan.
C
C ++
Saat membandingkan kode, Anda harus selalu berhati-hati bahwa Anda membandingkan suka untuk suka dan bahwa Anda memahami implikasi dari apa yang dilakukan kode Anda. Kadang-kadang bahkan contoh paling sederhana pun lebih rumit daripada yang disadari sebagian orang.
sumber
std::endl
adalah fungsi yang setara dengan menulis baris baru ke aliran stdio buffer-line.stdout
, khususnya, harus berupa buffer-line atau unbuffered ketika terhubung ke perangkat interaktif. Linux, saya percaya, menekankan opsi line-buffered.std::endl
untuk menampilkan baris baru.setvbuf(3)
? Atau apakah Anda bermaksud mengatakan bahwa defaultnya adalah buffer line? FYI: Biasanya semua file memiliki buffer blok. Jika aliran merujuk ke terminal (seperti stdout biasanya), itu adalah buffer line. Standard stream stream stderr selalu tidak dibangun secara default.printf
memerah secara otomatis saat bertemu dengan karakter baris baru?Sementara jawaban teknis yang ada sudah benar, saya pikir pertanyaannya akhirnya berasal dari kesalahpahaman ini:
Ini hanya pembicaraan pemasaran dari komunitas C ++. (Agar adil, ada pembicaraan pemasaran di setiap komunitas bahasa.) Itu tidak berarti sesuatu yang konkret yang bisa Anda andalkan.
"Anda membayar untuk apa yang Anda gunakan" seharusnya berarti bahwa fitur C ++ hanya memiliki overhead jika Anda menggunakan fitur itu. Tetapi definisi "suatu fitur" tidak granular tanpa batas. Seringkali Anda akan mengaktifkan fitur yang memiliki banyak aspek, dan meskipun Anda hanya membutuhkan sebagian dari aspek-aspek tersebut, seringkali tidak praktis atau mungkin bagi implementasi untuk menghadirkan fitur tersebut secara parsial.
Secara umum, banyak (walaupun bisa dibilang tidak semua) bahasa berusaha untuk menjadi efisien, dengan berbagai tingkat keberhasilan. C ++ ada di suatu tempat dalam skala, tetapi tidak ada yang istimewa atau ajaib tentang desainnya yang akan memungkinkannya untuk berhasil sepenuhnya dalam tujuan ini.
sumber
<cstdio>
dan tidak memasukkan<iostream>
, sama seperti cara Anda mengompilasinya-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables
.Fungsi Input / Output dalam C ++ ditulis dengan elegan dan dirancang agar mudah digunakan. Dalam banyak hal mereka adalah karya untuk fitur berorientasi objek di C ++.
Tetapi Anda memang menyerah sedikit kinerja sebagai imbalan, tapi itu diabaikan dibandingkan dengan waktu yang diambil oleh sistem operasi Anda untuk menangani fungsi-fungsi di tingkat yang lebih rendah.
Anda selalu dapat kembali ke fungsi gaya C karena mereka adalah bagian dari standar C ++, atau mungkin menyerahkan portabilitas sama sekali dan menggunakan panggilan langsung ke sistem operasi Anda.
sumber
std::basic_*stream
bawah) tahu eadaches yang masuk. Mereka dirancang untuk menjadi sangat umum dan diperluas melalui warisan; tetapi pada akhirnya tidak ada yang melakukannya, karena kerumitannya (ada buku yang ditulis di iostreams), sehingga perpustakaan baru lahir hanya untuk itu (misalnya boost, ICU dll). Saya ragu kita akan pernah berhenti membayar kesalahan ini.Seperti yang Anda lihat di jawaban lain, Anda membayar ketika Anda menautkan di perpustakaan umum dan memanggil konstruktor kompleks. Tidak ada pertanyaan khusus di sini, lebih banyak keluhan. Saya akan menunjukkan beberapa aspek dunia nyata:
Barne memiliki prinsip desain inti untuk tidak membiarkan efisiensi menjadi alasan untuk tetap di C daripada C ++. Yang mengatakan, orang perlu berhati-hati untuk mendapatkan efisiensi ini, dan ada efisiensi sesekali yang selalu berhasil tetapi tidak 'secara teknis' dalam spesifikasi C. Misalnya, tata letak bidang bit tidak benar-benar ditentukan.
Coba cari melalui ostream. Ya Tuhan, itu kembung! Saya tidak akan terkejut menemukan simulator penerbangan di sana. Bahkan printd stdlib () biasanya berjalan sekitar 50K. Ini bukan programmer yang malas: setengah dari ukuran printf ada hubungannya dengan argumen presisi tidak langsung yang kebanyakan orang tidak pernah gunakan. Hampir setiap perpustakaan prosesor yang benar-benar dibatasi membuat kode keluaran sendiri alih-alih printf.
Peningkatan ukuran biasanya memberikan pengalaman yang lebih berisi dan fleksibel. Sebagai analogi, mesin penjual otomatis akan menjual secangkir kopi seperti substansi untuk beberapa koin dan seluruh transaksi membutuhkan waktu kurang dari satu menit. Masuk ke restoran yang baik melibatkan pengaturan meja, duduk, memesan, menunggu, mendapatkan cangkir yang enak, mendapatkan tagihan, membayar formulir pilihan Anda, menambahkan tip, dan berharap hari yang baik di jalan keluar. Ini pengalaman yang berbeda, dan lebih nyaman jika Anda mampir ke teman untuk makan yang kompleks.
Orang-orang masih menulis ANSI C, meskipun jarang K&R C. Pengalaman saya adalah kami selalu mengompilasinya dengan kompiler C ++ menggunakan beberapa konfigurasi tweak untuk membatasi apa yang diseret. Ada argumen bagus untuk bahasa lain: Go menghapus overhead polimorfik dan preprocessor gila ; ada beberapa argumen bagus untuk pengemasan bidang yang lebih cerdas dan tata letak memori. IMHO Saya pikir setiap desain bahasa harus dimulai dengan daftar tujuan, seperti Zen of Python .
Ini merupakan diskusi yang menyenangkan. Anda bertanya mengapa Anda tidak dapat memiliki perpustakaan yang secara ajaib kecil, sederhana, elegan, lengkap, dan fleksibel?
Tidak ada Jawaban. Tidak akan ada jawaban. Itulah jawabannya.
sumber