2014-09-05 13 views
18

Hãy xem xét những điều sau:Có hợp lệ để xây dựng một `std :: ostream` từ một bộ đệm rỗng không?

std::ostream out(nullptr); 

Điều này có hợp pháp và được xác định rõ không?


Làm thế nào về nếu bây giờ tôi làm:

out << "hello world\n"; 

Đây có phải là hợp pháp và được xác định rõ? Nếu vậy, có lẽ đó là một không-op của các loại?

+0

tôi luôn luôn thêm một thử nghiệm đơn vị nếu tôi nghĩ rằng một cái gì đó như thế này nên làm việc, và dường như là hợp lệ. Bằng cách đó, nếu ai đó xây dựng cho một trình biên dịch/stdlib nền tảng khác thì họ biết nó bị hỏng. – paulm

+2

@paulm: Tôi gần như đồng ý, ngoại trừ các bài kiểm tra đơn vị không phải là điều bạn nên dựa vào để xác thực tính xác định tốt. –

+0

Trừ khi nó truy cập bộ nhớ ngoài ranh giới hoặc một cái gì đó tôi không thấy một vấn đề? Nhưng sau đó một lần nữa thử nghiệm đơn vị nên chạy với xác minh ứng dụng được kích hoạt/valgrind vv – paulm

Trả lời

22

Có, pháp lý và được xác định rõ ràng để khởi tạo luồng đó. Bạn có thể hoán đổi nó một cách an toàn với một luồng khác hoặc cho nó một con trỏ mới (lần này là một bộ đệm mở rộng) sau đó. Các hoạt động đầu ra chính nó thực sự là một no-op.

Dưới đây là lý do:

  1. Việc xây dựng không có điều kiện tiên quyết không null, và chỉ có hậu điều này:

    [C++11: 27.7.3.2/2]: hậu: rdbuf() == sb.

  2. thú vị, nó làm cho một điểm rõ ràng rằng không có hoạt động được thực hiện trên sb trong constructor:

    [C++11: 27.7.3.2/4]: Ghi chú: Không thực hiện bất kỳ hoạt động trên rdbuf().

  3. Nhưng cũng lưu ý:

    [C++11: 27.7.3.2/1]: Effects: Tạo thời đối tượng của lớp basic_ostream, gán giá trị ban đầu đối với lớp cơ sở bằng cách gọi basic_ios<charT,traits>::init(sb) (27.5.5.2).

  4. Đó init(sb) cuộc gọi có tác dụng thiết badbit trên dòng khi sb là NULL:

    [C++11: 27.5.5.2/3]: postconditions: Các postconditions của chức năng này được thể hiện trong Bảng 128.

    [C++11: Table 128]:[..]rdstate(): goodbit nếu sb không phải là con trỏ rỗng, nếu không badbit. [..]

  5. Kết quả hoạt động sẽ kết quả trong hành động tương đương với dereferencing một con trỏ null:

    [C++11: 27.7.3.1/2]: Hai nhóm chữ ký chức năng thành viên chia sẻ tài sản chung: các chức năng đầu ra định dạng (hoặc inserters) và các hàm đầu ra chưa được định dạng. Cả hai nhóm hàm đầu ra đều tạo ra (hoặc chèn) các ký tự đầu ra theo các hành động tương đương với việc gọi rdbuf()->sputc(int_type). Họ có thể sử dụng các thành viên công cộng khác của basic_ostream ngoại trừ việc họ sẽ không gọi bất kỳ thành viên ảo nào của rdbuf() ngoại trừ overflow(), xsputn()sync().

    ngoại trừ nó không bao giờ được đến đây, bởi vì đối với basic_ostream::sentry xây dựng:

    [C++11: 27.7.3.4/3]: Nếu, sau khi chuẩn bị bất kỳ hoàn tất, os.good()true, ok_ == true khác, ok_ == false.

    và, cho explicit operator basic_ostream::sentry::bool() const;:

    [C++11: 27.7.3.4/5]: Effects: Trả ok_.

    và:

    [C++11: 27.7.3.7/1]: Mỗi chức năng đầu ra chưa định dạng bắt đầu thực hiện bằng cách xây dựng một đối tượng của lớp sentry. Nếu đối tượng này trả về true, trong khi chuyển đổi thành giá trị loại bool, hàm sẽ cố gắng tạo ra kết quả được yêu cầu. [..]

    & hellip; ngụ ý là rằng không có hoạt động sản xuất diễn ra ở tất cả khi badbit đã được thiết lập.

This was also the case in C++03.

+1

+1 Điều Cooool! Điều cần biết, cách tạo một '/ dev/null' một cách hiệu quả bằng cách sử dụng' std :: ostream'. –

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