Apa pentingnya termasuk
ios_base::sync_with_stdio(false);
cin.tie(NULL);
dalam program C ++?
Dalam pengujian saya, ini mempercepat waktu eksekusi, tetapi apakah ada ujian yang harus saya khawatirkan dengan memasukkan ini?
Apakah 2 pernyataan selalu harus bersama, atau yang pertama cukup, yaitu mengabaikan cin.tie(NULL)
?
Juga, apakah diizinkan untuk menggunakan perintah C dan C ++ secara simultan jika nilainya telah disetel ke false
?
https://www.codechef.com/viewsolution/7316085
Kode di atas bekerja dengan baik, sampai saya gunakan scanf/printf
dalam program C ++ dengan nilai as true
. Dalam hal ini, ia memberikan kesalahan segmentasi. Apa yang mungkin menjadi penjelasan untuk ini?
Jawaban:
Kedua panggilan memiliki arti berbeda yang tidak ada hubungannya dengan kinerja; fakta bahwa itu mempercepat waktu eksekusi adalah (atau mungkin ) hanya efek samping. Anda harus memahami apa yang masing-masing dari mereka lakukan dan tidak secara membabi buta memasukkan mereka dalam setiap program karena mereka terlihat seperti sebuah optimasi.
Ini menonaktifkan sinkronisasi antara aliran standar C dan C ++. Secara default, semua stream standar disinkronkan, yang dalam praktiknya memungkinkan Anda untuk mencampur C / C dan C ++ - gaya I / O dan mendapatkan hasil yang masuk akal dan diharapkan. Jika Anda menonaktifkan sinkronisasi, maka aliran C ++ diizinkan memiliki buffer independennya sendiri, yang menjadikan pencampuran C / dan C ++ - gaya I / O menjadi petualangan.
Perlu diingat juga bahwa aliran C ++ yang disinkronkan aman-thread (output dari utas yang berbeda mungkin saling berhubungan, tetapi Anda tidak mendapatkan balapan data).
Ini terlepas
cin
daricout
. Aliran yang diikat memastikan bahwa satu aliran disiram secara otomatis sebelum setiap operasi I / O pada aliran lainnya.Secara default
cin
terkait dengancout
untuk memastikan interaksi pengguna yang masuk akal. Sebagai contoh:Jika
cin
dancout
terikat, Anda dapat mengharapkan output memerah (yaitu, terlihat pada konsol) sebelum program meminta input dari pengguna. Jika Anda membatalkan streaming, program mungkin memblokir menunggu pengguna untuk memasukkan nama mereka tetapi pesan "Masukkan nama" belum terlihat (karenacout
buffered secara default, output memerah / ditampilkan pada konsol hanya atas permintaan atau ketika buffer sudah penuh).Jadi, jika Anda melepaskan
cin
daricout
, Anda harus memastikan untuk menyiramcout
secara manual setiap kali Anda ingin menampilkan sesuatu sebelum mengharapkan input aktifcin
.Sebagai kesimpulan, ketahui apa yang mereka masing-masing lakukan, pahami konsekuensinya, dan kemudian putuskan apakah Anda benar-benar menginginkan atau membutuhkan efek samping yang mungkin dari peningkatan kecepatan.
sumber
cout
buffered karena suatu alasan, jika Anda menyiramnya terlalu sering, ketika Anda tidak benar-benar membutuhkannya, Anda mungkin akan melihat peningkatan kinerja.scanf()
, menonaktifkan buffering sepenuhnya atau beralih ke buffering baris (yang seharusnya siram setelah baris baru atau ketika input dibaca daristdin
- lihat linux.die.net/man/3/setlinebuf ).Ini untuk menyinkronkan IO dari dunia C dan C ++. Jika Anda menyinkronkan, maka Anda memiliki jaminan bahwa pesanan semua IO persis seperti yang Anda harapkan. Secara umum, masalahnya adalah buffering IO yang menyebabkan masalah, sinkronisasi memungkinkan kedua dunia untuk berbagi buffer yang sama. Misalnya
cout << "Hello"; printf("World"); cout << "Ciao";
; tanpa sinkronisasi Anda tidak akan pernah tahu apakah Anda akan mendapatkanHelloCiaoWorld
atauHelloWorldCiao
atauWorldHelloCiao
...tie
memungkinkan Anda memiliki jaminan bahwa saluran IOs di dunia C ++ terikat satu sama lain, yang berarti misalnya setiap output telah memerah sebelum input terjadi (pikirkancout << "What's your name ?"; cin >> name;
).Anda selalu dapat mencampurkan C atau C ++ IO, tetapi jika Anda menginginkan perilaku yang masuk akal, Anda harus menyinkronkan kedua dunia. Hati-hati bahwa secara umum tidak disarankan untuk mencampurnya, jika Anda memprogram dalam C menggunakan C stdio, dan jika Anda memprogram dalam C ++ gunakan stream. Tetapi Anda mungkin ingin menggabungkan pustaka C yang ada ke dalam kode C ++, dan dalam kasus seperti itu diperlukan untuk menyinkronkan keduanya.
sumber
cout <<
tidak dapat mengubah urutan sehinggaCiaoHelloWorld
tidak mungkin untuk contoh kasus Anda. Sinkronisasi hanya tentang metode buffering yang berbeda.Menggunakan
ios_base::sync_with_stdio(false);
cukup untuk memisahkanC
danC++
stream. Anda dapat menemukan diskusi ini di Standard C ++ IOStreams dan Locales , oleh Langer dan Kreft. Mereka mencatat bahwa cara kerjanya ditentukan oleh implementasi.The
cin.tie(NULL)
panggilan tampaknya meminta decoupling antara kegiatan dicin
dancout
. Saya tidak bisa menjelaskan mengapa menggunakan ini dengan optimasi lain harus menyebabkan crash. Seperti yang disebutkan, tautan yang Anda berikan buruk, jadi tidak ada spekulasi di sini.sumber
Itu hanya hal biasa untuk membuat input cin bekerja lebih cepat.
Untuk penjelasan singkat: baris pertama mematikan sinkronisasi buffer antara stream cin dan alat stdio C-style (seperti scanf atau get) - jadi cin bekerja lebih cepat, tetapi Anda tidak dapat menggunakannya secara bersamaan dengan alat stdio .
Baris kedua melepaskan ikatan cin dari cout - secara default buffer cout memerah setiap kali Anda membaca sesuatu dari cin . Dan itu mungkin lambat ketika Anda berulang kali membaca sesuatu yang kecil kemudian menulis sesuatu yang kecil berkali-kali. Jadi garis mematikan sinkronisasi ini (dengan secara harfiah mengikat cin ke null, bukan cout ).
sumber