C ++: “std :: endl” ve “\ n”


569

Birçok C ++ kitabı bunun gibi örnek kodlar içerir ...

std::cout << "Test line" << std::endl;

... ben de bunu hep yaptım. Ama bunun gibi çalışan geliştiricilerden çok fazla kod gördüm:

std::cout << "Test line\n";

Birini diğerine tercih etmek için teknik bir neden var mı, yoksa sadece bir kodlama stili midir?




25
@derobert bu diğerinden daha yaşlı
Kira

3
@ Gerçekten de öyle. Ama diğerinin cevabı bana biraz daha iyi vuruyor, bu yüzden bunu bu şekilde yapmayı seçtim. Ayrıca, diğeri de biraz daha geniş, aynı zamanda kaplıyor '\n'.
derobert

stackoverflow.com/a/30968225/3163618 önemli bir performans farkı olabilir.
qwr

Yanıtlar:


473

Değişen satır sonu karakterleri, dosyanın metin modunda açık olduğunu varsayarsak, ikili istemediğiniz sürece aldığınız şey budur. Derlenen program, derlenen sistem için doğru olanı yazar.

Tek fark, std::endlçıktı arabelleğini temizler ve '\n'yapmaz. Tamponun sık sık yıkanmasını istemiyorsanız kullanın '\n'. Bunu yaparsanız (örneğin, tüm çıktıyı almak istiyorsanız ve program kararsızsa) kullanın std::endl.


24
Veya kullanmayı düşünün ::std::cerryerine ::std::couto tamponsuz ve her çıkış işlemleri gerçekleştirebilen kızardı beri.
Herşey

142
@Omnifarious: Hatalar için std :: cerr ayrılmamalıdır. İki dere birlikte senkronize edilmez, bu nedenle cout için bir metin çıkarırsanız arabelleğe alınabilir ve serr doğrudan çıkışa gider, bu da karışık modlu bir ekranla sonuçlanır. Serr'i olması gerektiği gibi kullanın (hatalar) ve tasarlandığı şey için cout (normal etkileşim) kullanın.
Martin York

23
@Lucas: '\ n' den fazla platform farkında değil.
CB Bailey

32
@LokiAstari: stderr"Hatalar" diyorum . Aksine, bant dışı teşhis mesajları için, eğer isterseniz. Sadece ./prog > filegerçek program yükünü söylemek ve saklamak mümkün olmalıdır , ancak program normal etkileşimde bile çok daha fazla durum bilgisi çıkarmak isteyebilir.
Kerrek SB

13
"Birçok uygulamada, standart çıktı satır arabelleklidir ve std :: cout.sync_with_stdio (false) yürütülmedikçe '\ n' yazmak yine de bir floşa neden olur." buradan kopyalandı
GuLearn

249

Fark aşağıdakilerle açıklanabilir:

std::cout << std::endl;

eşittir

std::cout << '\n' << std::flush;

Yani,

  • std::endlÇıktıya hemen basmaya zorlamak istiyorsanız kullanın .
  • \nPerformans konusunda endişeleriniz varsa kullanın (muhtemelen <<operatörü kullanıyorsanız durum böyle değildir ).

Kullandığım \nen hatlarında.
Sonra std::endlbir paragrafın sonunda kullanın (ancak bu sadece bir alışkanlıktır ve genellikle gerekli değildir).

Diğer hak taleplerinin aksine, \nkarakter yalnızca akış bir dosyaya gidiyorsa ( std::cinve std::coutözel ancak hareketsiz dosyalar (veya dosya benzeri) ise) satır sonunun doğru platform sırasına eşlenir .


5
Birçok durumda, çünkü kırmızı ringa "çıkışı hemen görecek" coutbağlıdır cinEğer giriş okursanız gelen, yani cin, coutilk kızarmış olacak. Ancak cin, okuma çubuğu olmadan bir ilerleme çubuğu veya başka bir şey görüntülemek istiyorsanız , o zaman yıkama işleminin yararlı olduğuna emin olun.
Chris Jester-Young 30'11

9
@LokiAstari: << işleci kullanıyorsanız, muhtemelen performans konusunda endişe duymuyorsunuz - neden? operator<<Performans olmadığını ya da performans için hangi alternatifin kullanılacağını bilmiyordum. Lütfen bunu daha iyi anlayabilmem için bazı materyallere yönlendirin
legends2k

8
@ legends2k: C ++ akışlarının C printf () kadar performans göstermediği eski bir eş hikayesi var. Bir dereceye kadar doğru olsa da, hızdaki ana fark, C ++ akışlarını yanlış kullanan kişilerden kaynaklanmaktadır. stackoverflow.com/a/1042121/14065 C ++ 'da iostreams ile C-stream senkronize etmeyi unutmayın sync_with_stdio(false)ve çıktınızı sürekli olarak yıkamayın. Ne zaman yapılacağını kütüphanenin halletmesine izin verin. stackoverflow.com/a/1926432/14065
Martin York

6
@Loki: sync_with_stdioiostreams'i stdio kadar hızlı yapan bir şehir efsanesi var . Gelmez
Ben Voigt

2
@BenVoigt: Yukarıdaki ifadelerime dikkat ettim (bu yüzden onlarla mutluyum). Stdio kadar performans göstermez (çünkü daha fazlasını yapar). AMA insanların şikayet ettiği performans boşluğunun birçoğu stdio ile senkronizasyondan kaynaklanıyor.
Martin York


30

Eğer kullanacaksanız, başka bir fonksiyon çağrısı var std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a) operatörü bir <<kez arar .
b) operatörü <<iki kez arar .


19
Açık olabilir, ancak genellikle ilk versiyonun bir çekimde ikinci versiyonun diğer iş parçacıklarından yazmalarla ayrılabileceği tek bir satır yazacağı dişli programlar üzerinde büyük bir etkisi vardır. Genellikle yeterince kendimi bu önlemek için std :: cout << "merhaba \ n" << std :: floş yazma bulmak.
smparkes

Ne olmuş std::cout << "Hello" << "\n";?
byxor

1
@byxor Diğer cevaplarda açıklandığı gibi tampon yıkama dışında hemen hemen aynı. Her neyse, iki dize değişmez değerini birle birleştirebileceğiniz zaman gereksizdir.
iBug

Yazdırılacak dize bir değişmez değilse, o zaman a<< durumunda da 2 çağrıları olur , bu nedenle bir veya iki (veya genel olarak iki işlev çağrısı) için bir ihtiyaç olduğunu iddia etmezdim ve arasındaki fark . <<\nendl
Enrico Maria De Angelis

Lol hayır, kullanmamın nedeni bu değil \ n.
Carlo Wood

28

Standart hakkında bu konuda okuma hatırladım, işte gidiyor:

Standart akışların nasıl davrandığını tanımlayan C11 standardına bakın, C ++ programları CRT ile arayüz oluşturduğundan, C11 standardı buradaki yıkama politikasını yönetmelidir.

ISO / IEC 9899: 201x

7.21.3 §7

Program başlangıcında, üç metin akışı önceden tanımlanmıştır ve açıkça açılmasına gerek yoktur - standart girdi (geleneksel girdiyi okumak için), standart çıktı (geleneksel çıktı yazmak için) ve standart hata (tanı çıktısını yazmak için). Başlangıçta standart hata akışı tam olarak arabelleğe alınmaz; standart giriş ve standart çıkış akışları, yalnızca akışın etkileşimli bir cihaza atıfta bulunmayacağı belirlenebiliyorsa tamamen arabelleğe alınır.

7.21.3 §3

Bir akış arabelleğe alınmadığında, karakterlerin kaynaktan veya hedeften en kısa zamanda görünmesi amaçlanır. Aksi takdirde karakterler birikebilir ve ana bilgisayar ortamına / ortamından bir blok olarak iletilebilir. Bir akış tamamen arabelleğe alındığında, karakterlerin bir arabellek doldurulduğunda bir ana bilgisayar ortamına veya bloktan iletilmesi amaçlanır. Bir akış satır arabelleğe alındığında, karakterlerin yeni satır karakteri ile karşılaşıldığında ana bilgisayar ortamına veya ana ortamdan bir blok olarak iletilmesi amaçlanır. Ayrıca, karakterlerin bir arabellek dolduğunda, arabelleksiz bir akışta giriş istendiğinde veya ana bilgisayar ortamından karakterlerin iletilmesini gerektiren bir satır arabellek akışında giriş istendiğinde ana bilgisayar ortamına bir blok olarak iletilmesi amaçlanır. .

Bu araçlar std::coutve std::cintam tamponlanır ancak ve ancak bunlar olmayan bir etkileşimli cihaz kastediyoruz. Başka bir deyişle, stdout bir terminale bağlanırsa, davranışta bir fark yoktur.

Ancak, std::cout.sync_with_stdio(false)çağrılırsa, '\n'etkileşimli cihazlarda bile sifona neden olmaz. Aksi takdirde '\n', std::endldosyalara piping yapılmadığı sürece eşdeğerdir : c ++ ref on std :: endl .


19

Her ikisi de uygun satır sonu karakterlerini yazacaktır. Bu endl'e ek olarak tamponun işlenmesine neden olur. Dosya I / O yaparken genellikle endl kullanmak istemezsiniz, çünkü gereksiz işlemler performansı etkileyebilir.



10

Qt ve endlkullanırsanız, yanlışlıkla endlsize şaşırtıcı sonuçlar veren bir yanlış kullanabilirsiniz. Aşağıdaki kod snippet'ine bakın:

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>

// notice that there is no "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution!" << endl;
    // This prints something similar to: "Finished Execution!67006AB4"
    return qapp.exec();
}

(Doğru olurdu) endlyerine yazdım std::endlve görünüşe göre qtextstream.h (QtCore bir parçası olan) endliçinde tanımlanan bir işlev olduğunu unutmayın .

Olası ad alanı sorunlarını tamamen "\n"ortadan endlkaldırmak yerine kullanmak . Bu, sembollerin genel ad alanına (Qt'nin varsayılan olarak yaptığı gibi) neden yerleştirilmesinin kötü bir fikir olduğuna da iyi bir örnektir.


31
Urgh! Kim olmak ister ki using namespace std;? :-)
Steve Folly

2
Pis. Yorum için teşekkürler, eminim başkaları buna girecek.
Kafa Geek

@SteveFolly yapıyorum. Neden olmasın?
ʇolɐǝz ǝɥʇ qoq

@ ʇolɐǝzǝɥʇqoq Başlık dosyalarında yapmadığınız sürece sorun yok.
smerlin

1
@ ʇolɐǝzǝɥʇqoq Lütfen kaçının using namespace std;. Kötü uygulama olarak kabul edilir. Bkz. Neden “namespace std kullanılıyor”; kötü uygulama olarak mı değerlendirildi?
LF

2

Her zaman sadece std :: endl kullanma alışkanlığım oldu, çünkü görmek kolay.


2

std::endlManipülatör eşdeğerdir '\n'. Ancak std::endlher zaman akışı temizler.

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush

1

Programınızı kendi dizüstü bilgisayarınız dışında bir şey üzerinde çalıştırmak istiyorsanız, asla endlifadeyi kullanmayın . Özellikle çok sayıda kısa satır yazıyorsanız veya bir dosyaya sık sık tek karakterler gördüğüm için. endlNFS gibi ağa bağlı dosya sistemlerini kullanmanın bilinmesi.


Bu kızarıklıktan mı kaynaklanıyor? Bunun nasıl mümkün olabileceğini görebiliyorum.
Head Geek

@ Gerçekten de. Ayrıca disk IO performansını bozduğunu gördüm.
sbi

0

İle referans Bu ise yalnızca çıkış I / O manipülatör .

std::endlUçlar çıktı dizi os bir satır karakteri ve sanki çağırarak basması os.put(os.widen('\n'))ve ardından os.flush().

Ne zaman kullanılır:

Bu manipülatör hemen bir çıktı hattı üretmek için kullanılabilir ,

Örneğin

uzun süren bir işlemden çıktı görüntülerken, birden çok iş parçacığının günlük etkinliğini veya bir programın beklenmedik şekilde çökebilecek günlük etkinliğini görüntüler.

Ayrıca

Eğer ortaya çıkan işlem herhangi bir ekran G / Ç işlemi gerçekleştiriyorsa, std :: system çağrısından önce std :: cout öğesinin açıkça yıkanması gerekir. Diğer normal etkileşimli G / Ç senaryolarında, std :: cout ile kullanıldığında std :: endl gereksizdir, çünkü std :: cin, std :: cerr çıktısı veya program sonlandırması herhangi bir girdiyi std :: cout çağrısına zorlar .flush (). Bazı kaynaklar tarafından teşvik edilen '\ n' yerine std :: endl kullanımı çıktı performansını önemli ölçüde düşürebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.