Significato di ios_base :: sync_with_stdio (false); cin.tie (NULL);


147

Qual è il significato dell'inclusione

ios_base::sync_with_stdio(false);
cin.tie(NULL);

nei programmi C ++?

Nei miei test, accelera i tempi di esecuzione, ma c'è un caso di cui dovrei preoccuparmi includendolo?

Le 2 affermazioni devono sempre essere insieme o la prima è sufficiente, ovvero ignorare cin.tie(NULL)?

Inoltre, è consentito utilizzare comandi C e C ++ simultanei se il suo valore è stato impostato su false?

https://www.codechef.com/viewsolution/7316085

Il codice sopra ha funzionato bene, fino a quando non ho usato scanf/printfun programma C ++ con il valore as true. In questo caso, ha generato un errore di segmentazione. Quale potrebbe essere la possibile spiegazione per questo?


Lo hai effettivamente usato con false. Il tuo codice dice così ???
Suraj Jain,

Risposte:


232

Le due chiamate hanno significati diversi che non hanno nulla a che fare con le prestazioni; il fatto che acceleri i tempi di esecuzione è (o potrebbe essere ) solo un effetto collaterale. Dovresti capire cosa fa ognuno di loro e non includerli ciecamente in ogni programma perché sembrano un'ottimizzazione.

ios_base::sync_with_stdio(false);

Ciò disabilita la sincronizzazione tra i flussi standard C e C ++. Per impostazione predefinita, tutti i flussi standard sono sincronizzati, il che in pratica consente di mescolare I / O di tipo C e C ++ e ottenere risultati sensibili e attesi. Se disabiliti la sincronizzazione, i flussi C ++ possono avere i loro buffer indipendenti, il che rende un'avventura il mix di I / O in stile C e C ++.

Inoltre, tieni presente che i flussi C ++ sincronizzati sono thread-safe (l'output di thread diversi può intercalare, ma non ottieni corse di dati).

cin.tie(NULL);

Questo scioglie cinda cout. I flussi collegati assicurano che uno stream venga scaricato automaticamente prima di ogni operazione I / O sull'altro stream.

Di default cinè legato per coutgarantire una ragionevole interazione dell'utente. Per esempio:

std::cout << "Enter name:";
std::cin >> name;

Se cine coutsono collegati, è possibile aspettarsi che l'output venga scaricato (ovvero visibile sulla console) prima che il programma richieda l'input dell'utente. Se si slegano i flussi, il programma potrebbe bloccarsi in attesa che l'utente inserisca il proprio nome ma il messaggio "Inserisci nome" non è ancora visibile (poiché coutè bufferizzato per impostazione predefinita, l'output viene scaricato / visualizzato sulla console solo su richiesta o quando il il buffer è pieno).

Quindi, se si slegare cinda cout, è necessario assicurarsi di lavare coutmanualmente ogni volta che si desidera visualizzare qualcosa prima di aspettarsi ingresso cin.

In conclusione, sappi cosa fanno ognuno di loro, comprendi le conseguenze e poi decidi se vuoi davvero o se hai bisogno del possibile effetto collaterale del miglioramento della velocità.


Quando dici "devi assicurarti di scaricare manualmente cout ogni volta che vuoi visualizzare qualcosa prima di aspettarti un input su cin", che può essere semplice come aggiungere "... << std :: flush" o "... < <std :: endl "alla fine di ogni riga che inizia" std :: cout << ... ", giusto?
Alan,

4
Sì, è così semplice, ma fai attenzione con la parte "fine di ogni riga". coutviene bufferizzato per un motivo, se lo svuoti troppo spesso, quando in realtà non ne hai bisogno, potresti notare un calo delle prestazioni.
Ionut,

@Ionut esiste qualcosa di equivalente alla funzionalità tie () in C per scanf, printf?
iajnr,

1
@iajnr No, non direttamente. In C, puoi scaricare manualmente prima scanf(), disabilitare completamente il buffering o passare al buffering di linea (che dovrebbe scaricarsi dopo newline o quando l'input viene letto stdin- vedi linux.die.net/man/3/setlinebuf ).
Ionut,

1
A leetcode, migliora significativamente il tempo di esecuzione, forse questi siti Web competitivi fanno qualcosa di speciale per i test di input.
P0W,

18

Questo per sincronizzare gli IO dal mondo C e C ++. Se esegui la sincronizzazione, hai la garanzia che gli ordini di tutti gli IO sono esattamente ciò che ti aspetti. In generale, il problema è il buffering degli I / O che causa il problema, la sincronizzazione consente a entrambi i mondi di condividere gli stessi buffer. Per esempio cout << "Hello"; printf("World"); cout << "Ciao";; senza sincronizzazione non saprai mai se otterrai HelloCiaoWorldo HelloWorldCiaoo WorldHelloCiao...

tieti dà la garanzia che i canali di IO nel mondo C ++ sono collegati tra loro, il che significa ad esempio che ogni output è stato scaricato prima che si verifichino input (pensaci cout << "What's your name ?"; cin >> name;).

Puoi sempre mescolare IO IO C o C ++, ma se vuoi un comportamento ragionevole devi sincronizzare entrambi i mondi. Attenzione che in generale non è consigliabile mescolarli, se si programma in C usare C stdio e se si programma in C ++ usare flussi. Ma potresti voler mescolare le librerie C esistenti nel codice C ++ e in tal caso è necessario sincronizzare entrambe.


4
Anche senza sincronizzazione, le diverse chiamate a cout <<non possono cambiare l'ordine, quindi CiaoHelloWorldnon è possibile per il tuo esempio. La sincronizzazione si basa esclusivamente su diversi metodi di buffering.
Mikko Rantalainen,

3

L'uso ios_base::sync_with_stdio(false);è sufficiente per disaccoppiare i flussi Ce C++. Puoi trovare una discussione su questo in IOStreams e Local C ++ standard , di Langer e Kreft. Notano che il modo in cui funziona è definito dall'implementazione.

La cin.tie(NULL)chiamata sembra richiedere un disaccoppiamento tra le attività su cine cout. Non riesco a spiegare perché l'utilizzo di questo con l'altra ottimizzazione dovrebbe causare un arresto anomalo. Come notato, il link che hai fornito è errato, quindi nessuna speculazione qui.


0

È solo roba comune per far funzionare l'input cin più velocemente.

Per una rapida spiegazione: la prima riga disattiva la sincronizzazione del buffer tra il flusso cin e gli strumenti stdio in stile C (come scanf o gets) - quindi cin funziona più velocemente, ma non è possibile utilizzarlo contemporaneamente con gli strumenti stdio .

La seconda riga separa cin da cout : per impostazione predefinita, il buffer cout si scarica ogni volta che leggi qualcosa da cin . E questo può essere lento quando leggi ripetutamente qualcosa di piccolo, poi scrivi qualcosa di piccolo molte volte. Quindi la linea disattiva questa sincronizzazione (legando letteralmente cin a null anziché a cout ).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.