Jak to jest z buforowaniem wyjścia obiektu cout (klasy ostream)

0

Witam, ostatnio zaciekawił mnie fakt, w jaki sposób wyjście programu (używając iostream) jest buforowane. Wejście oczywiste, do napotkania znaku nowej lini lub przepełnienia bufora, w przypadku plików też zdaje się to być proste, ale w przypadku wyjścia standardowego jest dziwnie. Napisałem oto krótki programik, który pokazuje tą różnice:

#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;

// zamraża program na n sekund
void wait (int n)
{
  time_t time1=clock();;
  time_t time2=clock();
  while ((time2-time1)/CLOCKS_PER_SEC < n )
  {
       time2=clock();
       continue;
  }
};

int main (void)
{
   ofstream plik;
   plik.open("test.txt");
   
   cout<<"siema";
   plik<<"siema";
   
   wait(10); 
   
   plik<<endl;
   cout<<endl<<"KONIEC"<<endl;
   cin.get();
   cin.get();   
   return 0;
}

 

Pokazuje on, że używając wyjścia "cout" buforowanie jakby nie istniało, dane są wyświetlone natychmiast. Używając natomiast strumienia plikowego, buforowanie działa jak należy, w tym przypadku opróżniony zostaje bufor po wysłaniu znaku nowej lini. W przypadku cout, bufor zostaje opróżniony od razu, przez wysłaniem znaku nowej lini. Może jestem zbyt ciekawski, ale mógłby mi ktoś to wytłumaczyć ?:)

0

U mnie napis na konsoli pojawia się dopiero po 10 sekundach, działa jak powinno. Może masz std::unitbuf na std::cout?

Pamiętaj, że to nie sam znak nowej linii powoduje opróżnienie bufora. Manipulator std::endl to std::flush + '\n'. "siema\n" nie spowoduje, że bufor zostanie opróżniony. Z tego powodu nie powinno się używać std::endl tylko dlatego, że potrzeba znaku nowej linii - przy wypisywaniu wielu linii może to poważnie spowolnić program, bo za każdym razem bufor jest opróżniany.

0

Tak tak, pamiętam o tym. A co do napisu to hehe, dziwne, u mnie od razu wyskakuje, ale widać zależy to od implementacji, dzięki za sprawdzenie :)

0

a spróbuj w pierwszej linii dodać ios_base::sync_with_stdio(0);
możliwe, że przez synchronizacje z printf'em od razu jest wysyłane zamiast czekać (nigdy nie sprawdzałem)

0

'endl' jak i 'flush' mają opróżnić bufor. Ale dana implementacja biblioteki standardowej może sobie go opróżniać częściej, kiedy się jej tylko zamarzy. Może nawet mieć bufor zerowej wielkości i od razu wszystko przekazywać dalej.

Jeśli chodzi o wypisywanie na ekran - widocznie samo drukowanie znaków w konsoli jest na tyle kosztownym procesem, że nie opłaca się go opóźniać i bufor zaczyna być opróżniany jeszcze zanim dojdzie do jawnego endl'a czy flush'a. Na -Niksach zachowanie jest inne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1