2009-04-14 6 views
138

Нужно ли мне вручную позвонить close(), когда я использую std::ifstream?Нужно ли вручную закрыть 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 для закрытия файлов?

ответ

182

NO

Это то, что RAII для, пусть деструктор делать свою работу. Нет никакого вреда при закрытии его вручную, но это не C++, это программирование на 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().

+12

+1 - По крайней мере, тот, кто знает, что означает RAII :-) – Milan

+3

+1 Я не знал, что RAII обрабатывает это ... Я думаю, вы узнаете что-то новое каждый день – TStamper

+13

Использование вложенной области только для закрытия файла полностью искусственный - если вы хотите его закрыть, вызовите на нем close(). – 2009-04-14 15:23:02

43

Нужно закрыть файл?
NO

Следует ли закрывать файл?
Зависит.

Вас беспокоят возможные ошибки, которые могут возникнуть, если файл не удается правильно закрыть? Помните, что закрытые вызовы setstate (failbit), если он терпит неудачу. Деструктор вызовет функцию close() для вас автоматически из-за RAII, но не оставит вам способ проверить бит сбоя, поскольку объект больше не существует.

4

Нет, это делается автоматически деструктором ifstream. Единственная причина, по которой вы должны называть его вручную, состоит в том, что экземпляр fstream имеет большую область видимости, например, если он является переменной-членом длинного экземпляра живого класса.

+0

Другой причиной может быть проверка ошибок закрытия файла и предотвращение метаданных деструктора, если допускаются исключения с потоком. –

8

Я согласен с @Martin. Если вы пишете файл, данные все равно могут сидеть в буфере и не могут быть записаны в файл до тех пор, пока не вызывается close(). Не делая этого вручную, вы не знаете, была ли ошибка или нет. Не сообщать об ошибках пользователю очень плохо.