Мне нужно вручную вызвать close()
, когда я использую std::ifstream
?
Например, в коде:
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");
}
Мне нужно вызвать file.close()
вручную? Не следует ifstream
использовать RAII для закрытия файлов?
Ответ 1
NO
Это то, к чему относится RAII, пусть деструктор выполняет свою работу. Нет никакого вреда при закрытии его вручную, но это не С++-путь, он программируется на C с классами.
Если вы хотите закрыть файл до конца функции, вы всегда можете использовать вложенную область.
В стандарте (27.8.1.5. шаблон шаблона basic_ifstream) ifstream
должен быть реализован с элементом basic_filebuf
, содержащим фактический дескриптор файла. Он удерживается как член, так что, когда объект ifstream разрушается, он также вызывает деструктор на basic_filebuf
. И из стандарта (27.8.1.2) этот деструктор закрывает файл:
virtual ˜basic_filebuf();
Эффекты: Уничтожает объект класса basic_filebuf<charT,traits>
. Вызовы close()
.
Ответ 2
Вам нужно закрыть файл?
НЕТ
Вы должны закрыть файл?
Зависит.
Вы заботитесь о возможных ошибках, которые могут возникнуть, если файл не закрывается правильно? Помните, что setstate(failbit)
вызовы setstate(failbit)
если он терпит неудачу. Деструктор вызовет close()
для вас автоматически из-за RAII, но не оставит вам способа проверить бит сбоя, так как объект больше не существует.
Ответ 3
Я согласен с @Martin. Если вы пишете файл, данные все равно могут сидеть в буфере и не могут быть записаны в файл до тех пор, пока не будет вызван close()
. Не делая этого вручную, вы не знаете, была ли ошибка или нет. Не сообщать об ошибках пользователю очень плохая практика.
Ответ 4
Нет, это делается автоматически деструктором ifstream
. Единственная причина, по которой вы должны вызывать его вручную, заключается в том, что экземпляр fstream
имеет большую область видимости, например, если он является переменной-членом экземпляра класса с длительным сроком службы.
Ответ 5
Вы можете позволить деструктору делать свою работу. Но, как и любой объект RAII, могут быть ситуации, когда вызов close вручную может иметь значение. Например:
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
return 0;
}
записывает содержимое файла Но:
#include <stdlib.h>
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
exit(0);
}
не делает. Это редкие случаи, когда процесс внезапно завершается. Процесс сбоя может сделать то же самое.