Комментарии 6
"Определите, какой ресурс вы хотите управлять"
И так несколько раз. У автора проблемы с использованием падежей?...
Многие стандартные контейнеры C++ (например,
std::vector
иstd::string
) используют RAII для управления памятью, что обеспечивает их безопасность и эффективность.
То, что они используют RAII для управления памятью, обеспечивает только то, что из-за них не течёт память. Главное же состоит в том, что контейнеры корректно конструируют, переносят/копируют и уничтожают своё содержимое, что позволяет свободно хранить в них другие RAII-объекты, обладающие соответствующей семантикой копирования и/или перемещения. Например, те же unique_ptr.
Более того, поинтеры и конструкторы не используют RAII в том смысле, в котором их привёл автор. Они предоставляют механизм для пользователей этих классов использовать RAII путем создания этих сложных объектов на стеке. В этом весь смысл RAII в случае C++, о чем автор вообще не сказал явно.
Кстати, возникло ощущение, что в статье одно и то же написано раза по 3-4.
По моему пример с файлом не очень релевантный, так как std::ofstream и так автоматически закрывает файл при вызове деструктора.
Странно что не освещена основная проблема RAII - сокрытие ошибок при освобождении ресурса. Причина в том, что в деструкторе нельзя порождать исключения.
Как следствие, неверно вот это ваше утверждение:
FileHandler
гарантирует, что файл будет закрыт корректно
Нет. Он не гарантирует.
При возникновении ошибок при закрытии файла приложение о них не узнает. Например, последний "записанный" кусок всё ещё был в буфере объекта и при закрытии не смог записаться на диск потому что кончилось место. В результате у вас будет недозаписанный файл, но никто об этом не узнает.
Выход вызывать close явно, оставляя на RAII закрытие при раскрутке стека, что в целом лишь отодвигает, но не решает проблему полностью.
Гарантирует, что файл будет закрыт корректно. То, что при этом может возникнуть ошибка записи буфера, не означает, что файл не будет корректно закрыт. Смотрим сишную fclose -- даже если возникла ошибка, файл все равно будет корректно закрыт (т.е. об освобождении файла узнает ОС, file handle перестанет быть валидным).
Если вы хотите убедиться в том, что данные были успешно записаны, то логику вы должны строить, например, вокруг функции flush. Вокруг close ничего не построишь, это билет в один конец.
Концепция RAII (Resource Acquisition Is Initialization)