Używasz manipulatora strumienia (endl) lub znaku zmiany znaczenia nowego wiersza (\ n)?

12

Nie mam specyficznego kontekstu, w którym zadaję to pytanie, ale podczas czytania książki dla początkujących na C ++ zauważyłem użycie zarówno manipulatora strumienia endl, jak i znaku zmiany linii podczas obchodzenia się z obiektem strumienia.

Przykład jest następujący:

cout << "Hello World" << endl;
cout << "Hello World\n";

Moje pytania to:

  1. Czy bardziej odpowiednie jest użycie manipulatora strumienia (endl) w określonej sytuacji i znaku ucieczki w innej?
  2. Czy są wady wydajności, jeśli chodzi o użycie jednego z dwóch?
  3. Czy są one całkowicie wymienne?
  4. Przeczytałem, że sekwencja ucieczki jest przechowywana w pamięci jako pojedynczy znak. Czy to oznacza, że ​​bardziej odpowiednie jest użycie endl, jeśli masz mało pamięci?
  5. Czy manipulator strumienia ostatecznie zużywa pamięć w jakikolwiek sposób, jeśli tak, to czy jest to coś więcej niż sekwencja ucieczki?

Dzięki, StackExchange przeprosiny, jeśli opublikowałem to w niewłaściwej sekcji, pomyślałem, że liczy się to jako struktury danych.

king9x
źródło
2
endl powoduje również flush na niektórych strumieniach, '\ n' nie.
James

Odpowiedzi:

12

o << std::endl jest równoważne z następującym kodem:

o.put(o.widen('\n'));
o.flush();

Innymi słowy, powinieneś używać tylko std::endlwtedy, gdy potrzebujesz opróżnić strumień. Na przykład:

  • Za chwilę wykonasz czasochłonną operację i chcesz mieć pewność, że wyświetlisz komunikat, zanim to zrobisz.
  • Na Twój wynik czeka inny proces.
  • Jeśli działa więcej niż jeden wątek lub proces, może być konieczne opróżnienie danych wyjściowych, aby dane wyjściowe z każdego wątku lub procesu były wyświetlane poprawnie. (W przeciwnym razie możesz uzyskać pozornie losowe bloki wyjściowe przeplatane w niewygodnych odstępach czasu.)

Jeśli nie musisz opróżniać strumienia, użyj \nzamiast std::endl. Dodatkowe połączenia flushmogą zaszkodzić wydajności (czasami znacznie).

Aby uzyskać więcej informacji, zobacz cppreference.com .

Jeśli chodzi o użycie pamięci: martwienie się o \nkontra std::endljest prawie na pewno niepotrzebną mikrooptymalizacją, ale ogólnie spodziewam się, że zajmę \nmniej pamięci. \nto tylko jeden bajt na końcu literału łańcucha, podczas gdy zapis std::endljest tłumaczony przez kompilator na (prawdopodobnie wstawione) wywołania funkcji do puti flush.

Różnice w zakończeniach linii specyficzne dla platformy (Windows \r\nkontra Linux i OS X \n) są obsługiwane na niższym poziomie niż std::endli \n:

  • Jeśli strumień jest otwierany w trybie tekstowym, to jeśli piszesz \n, automatycznie tłumaczy go na odpowiednie zakończenie linii właściwe dla platformy. Jeśli czytasz zakończenie linii specyficzne dla platformy, strumień automatycznie tłumaczy go na \n.
  • Jeśli strumień jest otwierany w trybie binarnym, wtedy przekazują wszelkie zakończenia linii dosłownie i to zależy od Ciebie.
  • Dla std::couta std::cinw szczególności, są one traktowane tak, jakby oni w trybie tekstowym.
Josh Kelley
źródło
1

1) Użyj przenośności endl. Nowymi wersjami systemu Windows są \r\nLinux \ni Mac \r. Edycja: Zgodnie z komentarzami zakończenia specyficzne dla systemu linii są obsługiwane na niższym poziomie.

2) endlopróżnia strumień, "\n"nie robi.

3) Zależy od przenośności.

Jeśli chodzi o wykorzystanie pamięci, możesz ją zminimalizować, przepłukując ją do innej pamięci tak często, jak to możliwe endl. Zmniejszy to jednak wydajność.

Edycja: Usuń kilka błędów.

Kent
źródło
2
Mac jest oparty na systemie Unix od OS X, a zatem działa również \nna każdej nowoczesnej maszynie.
7
Przepraszam, ale to nieprawda. endli \nsą równoważne w odniesieniu do zakończeń linii specyficznych dla platformy; różnice między platformami są obsługiwane na niższym poziomie.
Josh Kelley
2
Twój pierwszy punkt jest błędny. endl () wysyła „\ n” do strumienia (oprócz opróżniania). Znak „\ n” jest konwertowany na specyficzny dla platformy End of line sequence(przy założeniu trybu tekstowego). Po End of line sequenceodczytaniu z pliku jest ponownie konwertowany na „\ n”. Punkt 3) jest wątpliwy. Ostatni akapit jest znowu niepoprawny: Opróżnianie nie oszczędza miejsca, a opróżnianie bardziej niż wymagane spowolni kod (celem bufora jest poprawa wydajności zapisu na wolnym urządzeniu).
Martin York,