표준 C++ 스트림 오브젝트 (std::cin
, std::cout
, std::cerr
및 std::clog
)에 대한 디폴트 설정은 대응하는 스트림 C (stdin
, stdout
및 stderr
)와 동기화되어 있다는 것이다. 동기화는 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의 동작에서 동기화 될 때 그것을 얻을 수 있습니다.
그것은'cout'이 어디로 갈 것인지에 달려 있습니다. 터미널 ('대화 형 장치')로 간다면 완전히 버퍼링 될 수 없습니다. 일반적으로 줄 바꿈으로 인해 줄 바꿈이 인쇄 된 후 문자가 나타나거나 이론적으로 버퍼링되지 않을 수 있습니다. 파이프 나 파일 또는 다른 비 대화식 목적지로가는 경우,'endl'은 스트림이 완전히 버퍼링 되더라도 데이터를 강제로 내보내므로 보통 그렇습니다. –
새로운 줄 문자도'endl'도 제공하지 않았는지 알고 싶었습니다. 일단 프로그램의 끝에 도달하면'stdout'에 결과가 출력 될 것인가, 터미널에 대해서는 알지만 모든 것에 적용됩니다 'stdout'의 종류? – CaptainDaVinci
예, 파일 스트림이 프로그램의 (정상적인) 끝에서 닫히면 보류중인 출력이 플러시됩니다. 버퍼가 가득 차면 플러시됩니다. 프로그램이 중단되면 대기중인 출력은 대개 플러시되지 않습니다. –