2014-11-17 20 views
16

Chỉ cần đọc một bài báo cũ nhưng thú vị bằng "Scott Meyers"Is std :: cout buffered?

http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf

Về cơ bản nó là về thích sử dụng '\n' qua std::endl (mà tôi đồng ý với và đã sử dụng tăng thêm tương tự cho năm).

NHƯNG phần cuối cùng cho thấy đây không có trong cuốn sách của ông bởi vì toàn bộ điều đã được trả lại tranh luận vì hai điểm:

  1. std::cout không đệm.
  2. Trạng thái ios::unitbuf trên std :: cout không được xác định rõ ràng (do đó, việc thực thi phụ thuộc).

Tôi đã xem nhanh nhưng không thể tìm thấy tham chiếu tiêu chuẩn rõ ràng cho 1 là đúng sự thật. Có phải std::cout không bị đảo ngược với những gì tôi đã luôn hiểu không?

+0

Điều này có một số thông tin: http://stackoverflow.com/questions/11392511/c-buffered-stream-io – stijn

Trả lời

2

Từ những gì tôi đọc biểu mẫu here, cout thường được đệm, nhưng khi phát hiện nó in ra môi trường tương tác, như bảng điều khiển, nó rơi trở lại không bị chặn.

Vì vậy, nếu bạn chuyển hướng đầu ra (bằng cách sử dụng '>' trong UNIX) thì đá hành vi đệm trong.

Xem thêm chi tiết trong bài viết liên kết.

+0

Bạn đang bối rối 'stdout' và' std :: cout'. Trước đây là dòng đệm cho thiết bị đầu cuối và khối đệm khác. –

+0

Những gì tôi nói cũng giống như Jerry Coffin và được viết theo tiêu chuẩn C99. – Alexandru

+1

Tôi không nghĩ rằng 'std :: cout' được đề cập trong tiêu chuẩn C99. –

16

Vâng, nó đệm:

C++ 11 27.4.2 [narrow.stream.objects]/3 : Đối tượng cout kiểm soát ra vào một bộ đệm dòng kết hợp với các đối tượng stdout

Bài viết đề cập đến phiên bản dự thảo năm 1995 về những gì đã trở thành tiêu chuẩn C++ 98. Tôi không biết có thể nói điều gì đó khác biệt hay không.

Đối với điểm 2, unitbuf là ban đầu sai trên tất cả các dòng (theo quy định của hậu điều kiện của các nhà xây dựng basic_ios), trừ cerrwcerr mà rõ ràng chỉ định khác. Một lần nữa, điều đó cũng có thể khác trong bản thảo cổ được nhắc đến.

+0

Tôi đã thấy điều đó. Nhưng nếu bạn đọc đoạn tiếp theo. Nó nói cùng một điều về std: cerr mà không phải là buffered. Vì vậy, tôi đã không tin rằng từ 'buffer' không bị quá tải ở đây. 'Đối tượng cerr điều khiển đầu ra đến một bộ đệm luồng liên kết với đối tượng stderr' –

+2

@LokiAstari:' cerr' cũng được đệm. Sự khác biệt là nó có bộ 'unitbuf', do đó nó được tự động xóa sau mỗi dòng. –

+0

OK. Điều đó có ý nghĩa. –

2

Theo trang này - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std :: cout được đệm. Tôi đã có một cái gì đó không in vì một vụ tai nạn đã xảy ra chương trình sau khi cout < < ... tuyên bố nhưng trước khi nó bị xô:

cout << "My error or flag message, but it's not flushed, so I never see it"; 

//system crash! 

cout << endl; 
9

Chuẩn C++ xác định tất cả đầu vào và đầu ra là "nếu như" tất cả đọc và viết cuối cùng đã xảy ra thông qua lần đọc và viết của các luồng C ([iostream.objects.overview]):

Đầu đề khai báo các đối tượng liên kết các đối tượng với luồng C chuẩn được cung cấp bởi các hàm được khai báo trong (27.9.2)), và bao gồm tất cả các tiêu đề cần thiết để sử dụng các đối tượng này.

Đối với hành vi của các dòng C tiêu chuẩn gắn liền với các đối tượng, chúng ta phải tham khảo các tiêu chuẩn C (§7.19.3):

Lúc khởi động chương trình, ba dòng văn bản được xác định trước và không cần mở một cách rõ ràng - đầu vào tiêu chuẩn (để đọc đầu vào thông thường), đầu ra tiêu chuẩn (để viết đầu ra thông thường) và lỗi chuẩn (để viết đầu ra chẩn đoán). Khi ban đầu mở, luồng lỗi chuẩn không được đệm đầy đủ; đầu vào tiêu chuẩn và luồng đầu ra tiêu chuẩn được đệm hoàn toàn nếu và chỉ khi luồng có thể được xác định không tham chiếu cho thiết bị tương tác.

Ở đây tôi trích dẫn từ tiêu chuẩn C99, nhưng tôi chắc chắn rằng (modulo thay đổi trong đánh số phần) giống nhau ở tất cả các phiên bản của tiêu chuẩn C.

+0

Từ bộ nhớ, điều này đã không thay đổi kể từ C90, và tương ứng với các yêu cầu trong hướng dẫn Unix ban đầu cho C. Mặt khác, anh ta hỏi về C++ và C++ có các quy tắc khác nhau. (Đặc biệt, C++ không có khái niệm về dòng đệm.) –

10

Trước tiên, không yêu cầu rằng std::cout (hoặc thậm chí std::cerr) là không bị chặn. Yêu cầu duy nhất là std::cerrstd::basic_ios::unitbuf thiết lập (để nó sẽ tuôn ra ở cuối mỗi chức năng đầu ra: << hoặc chức năng đầu ra không được định dạng). Trên Mặt khác, trừ khi bạn đã gọi std::basic_ios::sync_with_stdio(false), outputting đến suối C++ và xuất để tương ứng C suối (ví dụ: std::coutstdout) phải có những tác động tương tự. Về lý thuyết, điều này có thể được thực hiện bằng nhiều cách: stdout chức năng có thể mong muốn những std::cout, std::cout sản lượng có thể chuyển tiếp để stdout, hoặc họ có thể chia sẻ một số thực hiện đệm thông thường dưới mui xe. Trong thực tế, thực tế tất cả các triển khai đều có std::cout chuyển tiếp đến stdout.

C xác định rằng stderr không được đệm đầy đủ, và điều đó có thể stdout được đệm đầy đủ chỉ khi nó có thể được xác định không đề cập đến một thiết bị tương tác (đối với một số thực hiện được xác định ý nghĩa của "thiết bị tương tác"). Thông thường, stdout sẽ là dòng đệm (khái niệm không tồn tại trong iostream) và stderr sẽ là không bị chặn, nhưng điều đó không được đảm bảo theo tiêu chuẩn C (và có thể không phải là đúng ngày hôm nay — lần cuối cùng tôi thực sự xem đã hơn hai mươi năm trước đây). Dù sao, việc triển khai chỉ cần chuyển tiếp đến stdout sẽ thực hiện theo các quy tắc của việc triển khai C mà nó chuyển tiếp và một trong đó doesnt 'vẫn cần thực hiện một số bước để đảm bảo rằng đầu ra là std::coutstdout xuất hiện theo đúng thứ tự, và rằng stdout hoạt động "như thể" nó tuân thủ các quy tắc C.

Nếu bạn lo lắng về hiệu suất, thì bạn có thể muốn chạy một số thử nghiệm . Hãy thử đo thời gian cần để xuất ra một số std::ofstream bạn đã tự mở, so với thời gian cần để xuất ra std::cout (cả có và không có gọi là sync_with_stdio), với đầu ra được chuyển hướng. Sự khác biệt nên thú vị.

Các vấn đề liên quan