2009-04-14 28 views
138

Tôi có cần gọi theo cách thủ công close() khi tôi sử dụng std::ifstream không?Tôi có cần đóng thủ công ifstream không?

Ví dụ, trong các mã:

std::string readContentsOfFile(std::string fileName) { 

    std::ifstream file(fileName.c_str()); 

    if (file.good()) { 
     std::stringstream buffer; 
     buffer << file.rdbuf(); 
     file.close(); 

     return buffer.str(); 
    } 
    throw std::runtime_exception("file not found"); 
} 

Tôi có cần phải gọi file.close() cách thủ công? Không nên ifstream sử dụng số RAII để đóng các tệp?

Trả lời

182

NO

Đây là những gì RAII là cho, chúng ta hãy destructor làm công việc của mình. Không có hại trong việc đóng nó bằng tay, nhưng nó không phải là cách C++, nó lập trình trong C với các lớp.

Nếu bạn muốn đóng tệp trước khi kết thúc hàm, bạn luôn có thể sử dụng phạm vi lồng nhau.

Trong tiêu chuẩn (27.8.1.5 Mẫu lớp basic_ifstream), ifstream sẽ được triển khai với thành viên basic_filebuf đang nắm giữ tay cầm tệp thực tế. Nó được giữ như một thành viên để khi một đối tượng ifstream phá hủy, nó cũng gọi hàm hủy trên basic_filebuf. Và từ tiêu chuẩn (27.8.1.2), destructor rằng đóng file:

virtual ˜basic_filebuf();

Effects: Phá hủy một đối tượng của lớp basic_filebuf<charT,traits>. Gọi số close().

+12

+1 - Ít nhất một người biết RAII có nghĩa là gì :-) – Milan

+3

+1 Tôi không biết rằng RAII xử lý ... Tôi đoán bạn học điều gì đó mới hàng ngày – TStamper

+13

Sử dụng phạm vi lồng nhau chỉ để đóng tệp là hoàn toàn nhân tạo - nếu bạn muốn đóng nó, hãy gọi close() trên đó. –

43

Bạn có cần đóng tệp không?
NO

Bạn có nên đóng tệp không?
Tùy thuộc.

Bạn có quan tâm đến các điều kiện lỗi có thể xảy ra nếu tệp không đóng đúng không? Hãy nhớ rằng các cuộc gọi gần setstate (failbit) nếu nó không thành công. Destructor sẽ gọi close() cho bạn tự động vì RAII nhưng sẽ không để lại cho bạn một cách để kiểm tra bit không như đối tượng không còn tồn tại.

4

Không, điều này được thực hiện tự động bởi trình phá hủy ifstream. Lý do duy nhất bạn nên gọi nó là thủ công, là bởi vì cá thể fstream có một phạm vi lớn, ví dụ nếu nó là một biến thành viên của một cá thể lớp sống lâu.

+0

Một lý do khác có thể là kiểm tra lỗi đóng tập tin và để ngăn chặn ném destructor, nếu ngoại lệ được cho phép với luồng. –

8

Tôi đồng ý với @Martin. Nếu bạn ghi vào tệp, dữ liệu có thể vẫn đang nằm trên bộ đệm và có thể không được ghi vào tệp cho đến khi close() được gọi. Nếu không làm điều đó bằng tay, bạn không có ý tưởng cho dù có một lỗi hay không. Không báo cáo lỗi cho người dùng là một thực tế rất xấu.

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