2017-02-24 17 views
3

나는 과 같은 질문이 endl\n 사이에 여러 번 대답했음을 이해합니다. 그러나 endlstdout에 버퍼를 플러시 할 수 있으며, \n은 버퍼를 플러시 할 수 있다고 언급합니다.개행 문자가 버퍼를 플러시합니까?

그래서, 플러시 된 버퍼로 무엇을 이해하는 것은 주어진 입력 버퍼에 저장되고,이 endl를 통해 제공하는 경우에만 stdout에 전달, 또는 EXPLICT flush 기능이다. 그렇다면, 내가 기대 그 다음 코드 표시 방법

#include <iostream> 
#include <unistd.h> 

int main(void) 
{ 
    std::cout << "Hello\nworld"; 
    sleep(2); 
    std::cout << std::endl; 

    return 0; 
} 

:

후 2 초

Hello 
World 

그러나 실제 출력했다 :

Hello 

2 초 후

World 

왜 그렇습니까?

은 버퍼에 저장되지 \n해야 만 endl가 발생하는 버퍼는 stdout에 표시/플러시 될 것입니다,하지만 난 관찰하는 것과 \nendl 같은 방식으로 행동한다.

+6

그것은'cout'이 어디로 갈 것인지에 달려 있습니다. 터미널 ('대화 형 장치')로 간다면 완전히 버퍼링 될 수 없습니다. 일반적으로 줄 바꿈으로 인해 줄 바꿈이 인쇄 된 후 문자가 나타나거나 이론적으로 버퍼링되지 않을 수 있습니다. 파이프 나 파일 또는 다른 비 대화식 목적지로가는 경우,'endl'은 스트림이 완전히 버퍼링 되더라도 데이터를 강제로 내보내므로 보통 그렇습니다. –

+0

새로운 줄 문자도'endl'도 제공하지 않았는지 알고 싶었습니다. 일단 프로그램의 끝에 도달하면'stdout'에 결과가 출력 될 것인가, 터미널에 대해서는 알지만 모든 것에 적용됩니다 'stdout'의 종류? – CaptainDaVinci

+2

예, 파일 스트림이 프로그램의 (정상적인) 끝에서 닫히면 보류중인 출력이 플러시됩니다. 버퍼가 가득 차면 플러시됩니다. 프로그램이 중단되면 대기중인 출력은 대개 플러시되지 않습니다. –

답변

2

의견을 대답으로 변환.

어디서 cout이 가는가에 따라 다릅니다. 터미널 ('대화 형 장치')로 간다면 완전히 버퍼링 될 수 없습니다. 일반적으로 줄 바꿈으로 인해 줄 바꿈이 인쇄 된 후 문자가 나타나거나 이론적으로 버퍼링되지 않을 수 있습니다. 파이프 또는 파일 또는 다른 비 대화식 대상으로가는 경우 endl은 일반적으로 스트림이 완전히 버퍼링 되어도 데이터를 강제로 종료합니다.

나는 또한이 프로그램의 마지막에 도달하면 나는 어느 새 라인 문자도 endl, 출력이 stdout에 표시됩니다를 제공하는 경우, 나는 그것이 터미널 않습니다 알고 알고 싶어하지만,에 적용 할 수있다 모든 유형의 stdout?

예, 파일 스트림이 프로그램의 (정상적인) 끝에서 닫히면 보류중인 출력이 플러시됩니다. 버퍼가 가득 차면 플러시됩니다. 프로그램이 중단되면 대기중인 출력은 대개 플러시되지 않습니다.

3

표준 C++ 스트림 오브젝트 (std::cin, std::cout, std::cerrstd::clog)에 대한 디폴트 설정은 대응하는 스트림 C (stdin, stdoutstderr)와 동기화되어 있다는 것이다. 동기화는 C++ 스트림과 C 스트림을 교대로 액세스하면 일관된 동작이 발생 함을 의미합니다.C++ 표준이 동기화 구현 방법에 아무런 의무도하지 않습니다

std::cout << "hel"; 
fprintf(stdout, "lo,"); 
std::cout << " wo"; 
fprintf(stdout, "rld"); 

예를 들어, 다음 코드는 문자열 hello, world을 생산할 것으로 예상된다. 이를 구현하는 한 가지 방법은 std::cout (및 패밀리)에 대한 버퍼링을 비활성화하고 즉시 stdout에 액세스하는 것입니다. 즉 위의 예에서는 개별 문자를 즉시 ​​stdout에 쓸 수 있습니다.

문자가 실제로 stdout에 기록되면 stdout의 버퍼링 모드에 대한 기본 설정이 사용됩니다. 표준에서 사양을 찾을 수 없지만 일반적으로 버퍼링 모드가 stdout 인 기본값은 대화 형 스트림 (예 : 콘솔)에 연결되어있을 때 _IOLBF입니다. 즉, 버퍼가 줄 끝에서 플러시됩니다. 파일 쓰기의 기본값은 일반적으로 _IOFBF입니다. 즉, 전체 버퍼를 쓸 때 출력이 플러시됩니다. 결과적으로 std::cout에 개행을 쓰면 버퍼가 비워 질 수 있습니다.

C++의 스트림은 일반적으로 버퍼링되도록 설정됩니다. 즉, 파일에 개행 문자를 쓰면 일반적으로 출력이 즉시 나타나지 않습니다. 문자가 버퍼 오버플로를 일으키는 경우 즉시 버퍼가 비 버퍼로 설정됩니다. stdout과의 동기화는 종종 불필요합니다. 예를 들어, 프로그램이 항상 표준 출력에 쓰기 위해 std::cout을 사용하지만 표준 출력에 대한 출력이 매우 크게 느려지는 경우 (스트림에 대한 버퍼링을 비활성화하면 이 느림)입니다. 동기화를 비활성화 할 수 있습니다.

std::ios_base::sync_with_stdio(false); 

이렇게하면 모든 스트림 개체에 대한 동기화가 비활성화됩니다. 나쁜 구현의 경우 아무런 효과가 없지만 좋은 구현으로 인해 std::cout의 버퍼링이 가능 해져 속도가 상당히 빨라지고 라인 버퍼링이 비활성화 될 수 있습니다.

일단 C++ 스트림이 버퍼링되면 개행 문자를 쓸 때 플러시되도록하는 기본 제공 방법이 없습니다. 이것의 주된 이유는 라인 버퍼링을 다루는 것은 스트림 버퍼에 의한 각 캐릭터의 검사를 필요로 할 것이고 이것은 문자에 대한 벌크 연산을 효과적으로 막아 실질적으로 느려지 게 만듭니다. 필요한 경우 간단한 필터링 스트림 버퍼를 통해 회선 버퍼링을 구현할 수 있습니다. 예를 들면 :

class linebuf: public std::streambuf { 
    std::streambuf* sbuf; 
public: 
    linebuf(std::streambuf* sbuf): sbuf(sbuf) {} 
    int_type overflow(int_type c) { 
     int rc = this->sbuf->sputc(c); 
     this->sbuf->pubsync(); 
     return rc; 
    } 
    int sync() { return this->sbuf->pubsync(); } 
}; 
// ... 
int main() { 
    std::ios_base::sync_with_stdio(false); 
    linebuf sbuf(std::cout.rdbuf()); 
    std::streambuf* origcout = std::cout.rdbuf(&sbuf); 

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

    std::cout.rdbuf(origcout); // needed for clean-up; 
} 

TL; DR : C++ 표준은 라인 버퍼링의 개념을 가지고 있지 않지만 표준 I/O가 stdout의 C의 동작에서 동기화 될 때 그것을 얻을 수 있습니다.