Co oznacza opróżnianie bufora?

99

Uczę się C ++ i znalazłem coś, czego nie rozumiem:

Bufory wyjściowe mogą być jawnie opróżniane, aby wymusić zapisanie bufora. Domyślnie czytanie cinrzutów cout; coutjest również opróżniany, gdy program kończy się normalnie.

Czyli opróżnianie bufora (na przykład bufora wyjściowego): czy to czyści bufor, usuwając wszystko w nim, czy czyści bufor, wysyłając wszystko, co się w nim znajduje? A może opróżnienie bufora oznacza coś zupełnie innego?

Mohamed Ahmed Nabil
źródło

Odpowiedzi:

125

Rozważ zapisanie do pliku. To kosztowna operacja. Jeśli w swoim kodzie piszesz po jednym bajcie na raz, to każde zapisanie bajtu będzie bardzo kosztowne. Dlatego typowym sposobem na poprawę wydajności jest przechowywanie danych, które piszesz w tymczasowym buforze. Bufor jest zapisywany do pliku tylko wtedy, gdy jest dużo danych. Odkładanie zapisu i zapisanie dużego bloku za jednym razem poprawia wydajność.

Mając to na uwadze, opróżnianie bufora jest czynnością polegającą na przeniesieniu danych z bufora do pliku.

Czy to czyści bufor, usuwając wszystko w nim, czy też czyści bufor, wypisując wszystko, co w nim jest?

Ten ostatni.

David Heffernan
źródło
1
Dzięki. jeszcze jedna rzecz. Czytanie cin flushes cout. Czy to „czytanie cin” oznacza, że ​​użytkownik coś wprowadza, czy też jest poproszony o wprowadzenie czegoś?
Mohamed Ahmed Nabil
4
Czytanie cin ma miejsce, gdy używasz operatora strumienia do czytania z cin. Zazwyczaj chcesz opróżnić cout podczas czytania, ponieważ w przeciwnym razie dane wejściowe mogą pojawić się przed monitem.
David Heffernan
1
@DavidHeffernan O ile wiem, nigdy nie musisz opróżniać cout przed cin, ponieważ cin i cout są ze sobą powiązane (Stroustrup, Język programowania C ++, [io.tie]).
Sturmer
24

Zacytowałeś odpowiedź:

Bufory wyjściowe mogą być jawnie opróżniane, aby wymusić zapisanie bufora.

Oznacza to, że może być konieczne „opróżnienie” wyjścia, aby spowodować zapisanie go w źródłowym strumieniu (którym może być plik lub w wymienionych przykładach terminal).

Ogólnie rzecz biorąc, stdout / cout jest buforowane wierszowo: dane wyjściowe nie są wysyłane do systemu operacyjnego, dopóki nie napiszesz nowej linii lub jawnie nie opróżnisz bufora. Zaletą jest to, że coś podobnego std::cout << "Mouse moved (" << p.x << ", " << p.y << ")" << endlpowoduje tylko jeden zapis do bazowego „pliku” zamiast sześciu, co jest znacznie lepsze pod względem wydajności. Wadą jest to, że kod taki jak:

for (int i = 0; i < 5; i++) {
    std::cout << ".";
    sleep(1); // or something similar
}

std::cout << "\n";

wyświetli .....się natychmiast (dokładna sleepimplementacja, zobacz to pytanie ). W takich przypadkach będziesz potrzebować dodatkowego, << std::flushaby upewnić się, że dane wyjściowe zostaną wyświetlone.

Czytanie cinrzutów, coutwięc nie potrzebujesz do tego jawnego koloru:

std::string colour;
std::cout << "Enter your favourite colour: ";
std::cin >> colour;
tc.
źródło
Robię to dla (int i = 0; i <5; i ++) {std :: cout << "."; spać (1); } std :: cout << std :: endl; nie drukuje ..... od razu. Drukuje je z 1 milisekundą między nimi. Zauważysz to bardziej, gdy użyjesz snu (1000)
Mohamed Ahmed Nabil
@MohamedAhmedNabil Wyglądasz na mylącego sleep()(POSIX) z Sleep()(Windows)
tc.
1
Stara odpowiedź, ale tylko komentarz dotyczy mniej treści, a więcej przykładu. Kwalifikujesz się coutz przestrzenią nazw (tj. std::cout), Ale nie zrobiłeś tego w przypadku endl, co również powinno wymagać tej kwalifikacji.
vol7ron
1
Podoba mi się twój przykład. Ale myślałem, że endl opróżnia bufor, ale w twoim przykładzie \ n opróżnia bufor. Jestem zdezorientowany.
Naz
1
@Naz \ n nie opróżnia bufora; bufor jest opróżniany tylko na końcu programu w jego przykładzie (bufor jest zawsze opróżniany automatycznie na końcu programów w C ++). \ n prawdopodobnie został użyty tylko do formatowania. Ponadto masz rację, że std :: endl opróżnia bufor (tak samo jak std :: flush, ale to jest oczywiste).
liamnickell
4

Wyczyść bufor, wypisując wszystko.

Alex Chamberlain
źródło