Что произойдет, если я никогда не вызову close для открытого файлового потока?

Ниже приведен код для того же случая.

#include <iostream>
#include <fstream>

using namespace std;

int main () {
    ofstream myfile;
    myfile.open ("example.txt");
    myfile << "Writing this to a file.\n";
    //myfile.close();
    return 0;
}

Какая разница, если я раскомментирую строку myfile.close()?


person David Mnatsakanyan    schedule 31.01.2015    source источник
comment
Вы можете обнаружить, что этот вопрос SO также отвечает на ваш вопрос: Закрывает ли ofstream свои файлы автоматически?.   -  person Wai Ha Lee    schedule 04.03.2015


Ответы (4)


Нет никакой разницы. Деструктор файлового потока закроет файл.

Вы также можете положиться на конструктор, чтобы открыть файл вместо вызова open(). Ваш код можно сократить до этого:

#include <fstream>

int main()
{
  std::ofstream myfile("example.txt");
  myfile << "Writing this to a file.\n";
}
person juanchopanza    schedule 31.01.2015
comment
Или даже std::ofstream("example.txt")<<"Writing this to a file.\n"; - person Deduplicator; 01.02.2015

Чтобы подкрепить ответ juanchopanza ссылкой на std::fstream документацию

(деструктор)
[виртуальный](неявно объявленный)

уничтожает basic_fstream и связанный с ним буфер, закрывает файл (виртуальная общедоступная функция-член)

person πάντα ῥεῖ    schedule 31.01.2015

В этом случае ничего не произойдет и время выполнения кода очень меньше.

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

когда вы открываете файл, операционная система создает запись для представления этого файла и хранения информации об этом открытом файле. Таким образом, если в вашей ОС открыто 100 файлов, то в ОС будет 100 записей (где-то в ядре). Эти записи представлены целыми числами, такими как (...100, 101, 102....). Этот номер записи является дескриптором файла. Таким образом, это просто целое число, которое однозначно представляет открытый файл в операционной системе. Если ваш процесс открывает 10 файлов, ваша таблица процессов будет иметь 10 записей для файловых дескрипторов.

Кроме того, именно поэтому у вас могут закончиться файловые дескрипторы, если вы открываете много файлов одновременно. Что предотвратит запуск систем *nix, поскольку они постоянно открывают дескрипторы для заполнения /proc.

Аналогичная вещь должна произойти в случае всей операционной системы.

person Biplab Kundu    schedule 31.01.2015
comment
Это не помешает работе всей системы, приложение просто не сможет открыть больше файлов. - person Ruslan; 31.01.2015
comment
Это может помешать запуску всего вашего приложения. - person user253751; 31.01.2015
comment
Также обратите внимание, что Windows не использует целые числа для файловых дескрипторов и не называет их файловыми дескрипторами. - person user253751; 31.01.2015
comment
На самом деле, в ОС, совместимых с UNIX/POSIX, открытие 10 файлов приведет к тому, что таблица FD процесса будет содержать 13 записей: 10 для файлов, которые мы открыли, и 3 для стандартных потоков: stdin, stdout и stderr. - person ElementW; 31.01.2015
comment
Все это правильно, за исключением того, что наличие или отсутствие явного close для этой игрушечной программы не существенно изменит общее время ее выполнения. Деструктор вызывает close, а close ничего не делает, если он уже был вызван, так что разница порядка 10 дополнительных машинных инструкций. - person zwol; 01.02.2015
comment
@immibis HANDLE — это typedef для void * только для обратной совместимости; значение HANDLE функционально является целым числом. (В Win16, если мне не изменяет память, HANDLE были настоящими указателями на структуры данных ядра, но в Windows NT они были сделаны непрозрачными значениями, и поэтому все производное от них.) И, хотя я не могу найти, что это такое прямо сейчас, Я уверен, что существует ограничение на количество открытых файлов для каждого процесса. Однако вы правы в том, что это не маленькие целые числа, а значения 0, 1, 2 не являются специальными (вместо них есть другие специальные значения). - person zwol; 01.02.2015
comment
@zwol В Unix дескрипторы файлов гарантированно будут небольшими целыми числами; в Windows они имеют непрозрачный тип (который может быть целым числом, указателем или...) - person user253751; 01.02.2015
comment
@immibis Это непрозрачные целые числа; например, частью контракта ABI является все ядра HANDLE имеют значение, два младших бита которого равны нулю. - person zwol; 01.02.2015
comment
Деструктор закрывает файл, с файловыми дескрипторами проблем нет. -1 - person user541686; 01.02.2015
comment
@Mehrdad, нет проблем, если деструктор вызывается своевременно. Если вы откроете файл в main(), а затем войдете в основной цикл программы, не имеет значения, что файл будет автоматически закрыт при выходе из программы: вы фактически слили дескриптор файла. Точно так же, если ваша программа поддерживает список открытых файлов и не заботится о его очистке, деструктор не будет вызываться до тех пор, пока файл не будет удален из списка — до тех пор, пока дескриптор не будет фактически утерян. - person Mark; 01.02.2015
comment
Файловые дескрипторы и файловые дескрипторы — это две разные абстракции, и многие C и реализации C++ для Windows фактически имеют и то, и другое на разных уровнях. Последствия исчерпания дескриптора или дескриптора не являются ни такими простыми, ни такими радикальными (предотвращают работу систем), как утверждает этот бланк ответа. И контракт API для Win32 заключается в том, что непрозрачный означает непрозрачный; не следует предполагать ни целое число, ни указатель. - person JdeBP; 01.02.2015

В обычных условиях разницы нет.

НО в исключительных случаях (с небольшими изменениями) вызов закрытия может вызвать исключение.

int main()
{
    try
    {
        ofstream myfile;
        myfile.exceptions(std::ios::failbit | std::ios::badbit);
        myfile.open("example.txt");

        myfile << "Writing this to a file.\n";


        // If you call close this could potentially cause an exception
        myfile.close();


        // On the other hand. If you let the destructor call the close()
        // method. Then the destructor will catch and discard (eat) the
        // exception.
    }
    catch(...)
    {
        // If you call close(). There is a potential to get here.
        // If you let the destructor call close then the there is
        // no chance of getting here.
    }
}
person Martin York    schedule 03.02.2015