2012-05-09 7 views
1

버퍼링 된 스트림의 경우에는 버퍼에 가득 차서 모니터에 다시 기록 할 때까지 대기한다고 스트림에 설명되어 있습니다. 예를 들어 그들은 "버퍼가 가득"에 의해 의미합니까 무엇버퍼링 된 스트림과 버퍼링되지 않은 스트림

cout << "hi"; 
  1. . 그것은 무엇을 의미 하는가 cerr에 보내 모든 것이 바로 표준 오류 장치에 기록되는 것을 내 책에

    cerr << "hi"; 
    
  2. 을 말한다? 이 예 ch에서

    char *ch; 
    cin>> ch; // I typed "hello world"; 
    
  3. 는 "안녕하세요"와 "세계가"그것은 여전히 ​​버퍼에 그것은 미래의 진술의 결과에 영향을 미칠 것이라는 점을 의미합니까 무시됩니다에 할당 할 것인가?

+0

표준 참고 : 기본적으로'cout'가 stdio''와 동기화 및 기본입니다' stdio'는 라인 버퍼입니다. – ybungalobill

+2

사실, 두 번째 예제에서는 알 수없는 위치에서 메모리에 쓸 것이므로 정의되지 않은 동작이 발생합니다. ** 잘하면 ** 충돌이 발생합니다. –

답변

9

귀하의 책은별로 도움이되지 않습니다.

1) 출력 스트림은 std::streambuf으로 바이트를 보내고, 에는 버퍼가 포함될 수 있습니다. 및 std::ofstream에 의해 사용 된 std::filebuf (streambuf으로부터 유도 됨)은 일반적으로 버퍼링 될 것이다. 즉, 을 출력하면 문자가 즉시 출력되는 것은 아닙니다. flush() (직접 또는 간접적으로 std::endl을 사용하여) 스트림을 호출하여 flush()을 명시 적으로 요청하면 버퍼에 이 가득 찼을 때만 버퍼에 쓰여지고 운영 체제에 출력됩니다. 그러나 이것은 다를 수 있습니다. std::cout에 출력 stdout와 동기화되며, 대부분의 구현은 더 많거나 적은 출력 대화 형 장치에가는 경우 버퍼링 방식을 변경, std::cout에 대한 stdout의 규칙을 따릅니다.

어쨌든 확실하지 않은 경우 출력 이 실제로 프로그램에서 나가기를 원하면 flush에 대한 호출을 추가하기 만하면됩니다.

2) 책이 잘못되었습니다.

버퍼링 전략 중 하나는 unitbuf입니다. 이 설정하거나 (당신이 std::ostream 개체에서이 함수를 호출 할 수 있도록 std::ios_base::set()std::ios_base::unset()std::ios_basestd::ostream의 기본 클래스입니다) 재설정 할 수있는 std::ostream의 플래그입니다. unitbuf가 설정되면, std::ostream 모든 출력 기능의 끝에 flush() 에 대한 호출을 추가, 그래서 당신은 쓸 때 :

스트림 문자열 의 모든 문자 후 플러시됩니다
std::cerr << "hello, world"; 

출력 제공된 unitbuf이 제공됩니다. 시동시 unitbuf은 에 대해 으로 설정됩니다. 기본적으로 다른 파일에는 설정되어 있지 않습니다. 그러나 은 원하는대로 설정하거나 해제 할 수 있습니다. 을 std::cerr에 설정하지 말 것을 권장하지만, 대화 형 장치에 std::cout을 출력하는 경우에는 거기에 설정하는 것이 좋습니다.

여기서 질문의 모든 것은 streambuf에있는 버퍼입니다. 일반적으로 OS는 버퍼도 제공합니다. 버퍼를 플러시하는 것은 모두 문자를 OS로 전송하는 것입니다. 이 사실은 트랜잭션 무결성이 필요할 때 ofstream을 직접 사용할 수 없다는 것을 의미합니다.

3) 문자열이나 >>를 사용하여 문자 버퍼에 입력 한 다음 std::istream 최초의 공백을 선도 건너 뛰고가 에 있지만 다음에 공백을 포함하지 않는 입력. 표준의 공식적인 용어에서는 스트림에서 문자를 "추출"하여 을 다시 볼 수 없습니다 (스트림이 지원하는 경우 검색하지 않는 한). 다음 입력은 이전에 중단 된 부분을 픽업합니다. 다음 문자가 버퍼에 있거나 디스크에 남아 있는지 여부는 실제로는 과 관련이 없습니다. 그것은 여러 가지 수준 발생하고, OS 레벨에서, 장치에 따라 다양한 형태를 취한다는 점에서 입력 버퍼링이 다소 복잡

참고. 일반적으로 OS는 파일을 개의 섹터로 버퍼링하며, 종종 여러 섹터를 미리 읽습니다. OS는 항상 파일 끝에 도달하지 않는 한 만큼 많은 문자를 반환합니다. 대부분의 OS는 키보드를 한 줄씩 버퍼링합니다. 읽기 요청에서 전체 라인이 입력 될 때까지 읽기 요청을 반환하지 않으며 읽기 요청에서 현재 행의 끝을 넘어 문자를 반환하지 않습니다.std::ostream과 동일하게

std::istream는 각각의 개별 특성을 얻기 위해 하나를 사용하여, 출력을위한 streambuf 이용한다. 이 std::cin 인 경우 일반적으로 filebuf이됩니다. istream 이 문자를 요청하면 filebuf은 에 문자가있는 경우 해당 문자를 버퍼에서 하나를 반환합니다. 그렇지 않은 경우, 버퍼를 다시 채우려 고 시도 할 것이다. 은 예를 들어. 512 (또는 버퍼 크기가 무엇이든간에) OS의 문자. 위에서 설명한대로 기기의 버퍼링 정책에 따라 응답합니다. std::cin가 키보드에 연결되어, 당신은 당신이 입력 한 모든 문자가 결국 스트림에 의해 을 읽을 수 있습니다, "hello world"를 입력 한 경우 여하튼

. (당신이 >>를 사용하는 경우, 당신은
볼 수 없습니다 공백이 많이 이있을 수 있습니다.)

2

스트림은 효율성을 높이기 위해 버퍼이며 파일 및 콘솔 IO는 메모리 조작에 비해 매우 느립니다.

이 C++ 스트림에는 파일이나 출력에 쓸 모든 것을 포함하는 버퍼 (메모리 뱅크)가 있습니다.이 버퍼는 파일이 가득 차면 파일로 플러시됩니다. inverse는 입력에 대해 true이고 버퍼가 고갈되면 더 많이 가져옵니다. 4 비효율적 인 파일에 기록 될 것인가

std::cout << 1 << "hello" << ' ' << "world\n"; 

을 다음 있기 때문에

이 흐름에 매우 수입이다.

std :: cout, cin 및 cerr의 경우 이러한 유형의 버퍼링은 std :: printf 및 std :: puts 등과 함께 사용할 수 있도록 기본적으로 해제되어 있습니다. .

std::ios_base::sync_with_stdio(false); 

을하지만이 허위 또는 나쁜 일이 일어날 수 있습니다 설정되어있는 동안 C 스타일의 콘솔 출력을 사용하지 마십시오

(나는 일을 권장하는)를 다시 활성화합니다.

+0

예에서 "1hello world \ n"은 먼저 버퍼로 전달 된 다음 화면으로 전달됩니다. 하지만 내가 cerr << 1 << "hello"<< " '<<"world \ n "; 1이 화면에 전달되고 "안녕하세요"등등 ...이게 맞습니까? 덕분에 – AlexDan

+0

@AlexDan well "1hello world \ n"이 버퍼에 기록되고 입력이 사용자에게 필요할 때 화면에 기록되고 cin 추출 작업은 두 스트림을 동기화하여 cout이 플러시되도록합니다. std :: cout << std :: flush 또는 std :: cout << std :: endl;을 사용하여 수동으로 스트림을 플러시 할 때 또는 스트림이 파괴되고 닫힐 때 (IE의 std :: cout 프로그램 끝 또는 파일 범위 끝). – 111111

+0

@AlexDan Cerr과 Cout은 전송 된 파일 설명자에 따라 다르며, cout은 stdout으로 가고 cerr은 stderror로갑니다. 당신이 stdio와 동기화하지 않도록 설정하면 둘 다 버퍼링되고, 사실이면 둘 다 버퍼링되지 않습니다. 그것은'clog'가'cerr'와 동일하지만 항상 버퍼링된다고 믿습니다. – 111111

0
  1. 단말 쓰기를 호출 할 때마다 자주 데이터가 특정 양의 데이터 중 어느 하나가 입력되었는지 또는 버퍼 FFLUSH 또는 STD 수동 플러시 될 때까지 메모리에 저장된다 느린 일을 피하기 위하여, 느리게 :: endl. 이 결과는 예상 한 순간에 텍스트가 터미널에 쓰여지지 않을 때가 있습니다.

  2. 오류 메시지의 타이밍이 정상 출력보다 더 중요하므로 성능 적중이 무시되고 데이터가 버퍼링되지 않습니다. 그러나 문자열은 단일 데이터로 전달되기 때문에 하나의 호출 (루프 내의 어딘가에서)으로 작성됩니다.

  3. 세계는 여전히 버퍼에 있지만, 3 선 프로그램에서 시도해 보면이 사실을 증명하는 것이 쉽습니다. 그러나 할당되지 않은 메모리에 쓰기를 시도하기 때문에 예제가 실패합니다. 대신 std :: string으로 입력을 가져와야합니다.

+0

포인트 2가 실제로 올바르지 않습니다. 'std :: cerr'의'filebuf'는 여전히 평소와 같이 버퍼링합니다. 차이점은'unitbuf'가 설정된다는 것인데, 이는'ostream'이 각'>>'의 끝 부분에서 플러시를한다는 것을 의미합니다. (사실, 함수의 상단에 건설 된 보초 개체의 소멸자에 있음) –

+0

@JamesKanze는 버퍼를 플러시하는 유일한 방법입니다. fflush ot std :: endl; ? cout << "hello"는 어떨까요? cout << "world"; – AlexDan

+0

@AlexDan 아니요. 'unitbuf'가 설정되어 있지 않으면 모든 '<<'의 끝에 플러시가 발생합니다. –

1

1) 그들은 "버퍼가 가득"을 의미하는 무슨.메모리의 영역이있다 버퍼링 된 출력으로

, 그것은 실제로 출력에 기록되기 전에 당신이 쓰는 물건이 저장되어있는 버퍼를했다. cout << "hi"라고 말하면 문자열은 해당 버퍼에 복사되고 쓰여지지 않을 것입니다. cout은 실제로 메모리를 가득 채울 때까지 기다렸다가 실제로 쓰기 시작합니다.

일반적으로 실제로 데이터 쓰기를 시작하는 프로세스가 느리기 때문에 그 이유는 모든 문자에 대해 그렇게하는 경우 끔찍한 성능을 얻게되기 때문입니다. 버퍼가 사용되어 프로그램이 자주 수행하지 않아야하고 성능이 훨씬 향상됩니다.

2)이 cerr로 전송 모든 immediatly 표준 오류 장치에 기록되는 것을 내 책에서 말했다, 이것은 그 다음 '시간'을 보내고 의미합니까 'i'를 ...?

단지 버퍼가 사용되지 않는다는 것을 의미합니다. cerr은 이미 'h'와 'i'를 동시에 보낼 수 있습니다. 왜냐하면 이미 두 개가 이미 있기 때문입니다.

3)이 예제에서 ch는 "hello"에 할당되고 "world"는 무시되며 이는 버퍼에 남아 있으며 향후 명령문의 결과에 영향을 미칩니 까?

이것은 실제로 버퍼링과 관련이 없습니다. >> 연산자는 공백을 볼 때까지 읽도록 정의되어 있으므로 "hello"와 "world"사이의 공간에서 멈 춥니 다. 그러나 그렇습니다. 다음에 읽으면 "세계"가 생길 것입니다.

(대신 당신이해야 그 코드가 정의되지 않은 메모리 위치에 텍스트를 읽고 있기 때문에 동작을 정의되지 않은 한 후 실제로 사용 코드의 단지 의역이 아닌 경우 비록 :.

std::string s; 
cin >> s; 

)

2

작은 앱으로 직접 차이점을 확인할 수 있습니다.

#include <iostream> 
int main() { 
    std::cout<<"Start"; 
    //std::cout<<"Start"<<std::endl; // line buffered, endl will flush. 
    double j = 2; 
    for(int i = 0; i < 100000000; i++){ 
     j = i/(i+1); 
    } 
    std::cout<<j; 
    return 0; 
} 

두 "시작"문장의 차이점을 시험해보고 cerr로 변경하십시오. 그 차이는 버퍼링 때문입니다.

for 문은 내 리그에서 약 2 초가 걸리므로 i < 조건을 조정해야 할 수 있습니다.

+0

미안하지만 같은 결과가 나옵니다. 시작 후 1 초 후에 0 – AlexDan

+0

결과가 여기에 쓰이는 방식으로 결과가 나오면 버퍼링되지 않은 std :: cout이 있습니다. –

+0

또는 매우 느린 콘솔. Windows에서처럼 :) – sehe