Дескриптор файла RAII выглядит довольно просто, так что, я думаю, он уже реализован? Но я не нашел никакой реализации. Я нашел file_descriptor в boost::iostreams, но не знаю, то ли это, что я ищу.
Есть ли уже реализованный дескриптор файла RAII?
Ответы (3)
std::fstream
s поддерживают использование в стиле RAII — их можно открыть и даже протестировать при построении, и они автоматически сбрасываются и закрываются в деструкторе, хотя вы можете пропустить ошибки, если просто предполагаете, что это работает, поэтому вы можете захотеть сделать что-то более явное в код, если вам нужна надежность.
Например:
if (std::ifstream input(filename))
... use input...
else
std::cerr << "unable to open '" << filename << "'\n";
Если вы действительно хотите использовать файловые дескрипторы, вы можете настроить что-то вроде следующего по вкусу. Это немного длиннее, чем то, что просто вызывает close
, но если вы хотите сделать надежное программирование, вам нужно как-то проверять и обрабатывать ошибки....
struct Descriptor
{
Descriptor(int fd, const char* filename = nullptr)
: fd_(fd), filename_(filename)
{
if (fd < 0)
{
std::ostringstream oss;
oss << "failed to open file";
if (filename_) oss << " '" << filename_ << '\'';
oss << ": " << strerror(errno);
throw std::runtime_error(oss.str());
}
}
~Descriptor()
{
if (fd_ != -1 && close(fd_) == -1)
{
// throwing from destructors risks termination - avoid...
std::cerr << "failed to close file";
if (filename_) std::cerr << " '" << filename_ << '\'';
std::cerr << ": " << strerror(errno) << std::endl;
}
}
operator int() const { return fd_; }
private:
int fd_;
};
Применение:
try
{
Descriptor fd(open(filename, O_RDONLY), filename);
int nbytes = read(fd, ...);
...
}
catch ...
Зависит от того, что именно вы хотите.
Если вам действительно нужен дескриптор с областью действия, используйте:
std::unique_ptr<HANDLETYPE, closehandletypefunction> smartpointer;
Для указателей FILE
это будет выглядеть так
std::unique_ptr<FILE, int (*)(FILE *)> f(fopen("myfile.txt", "a"), fclose);
Затем FILE*
можно получить с помощью f.get()
. То же самое будет работать с файловыми дескрипторами (open
и close
из <fcntl.h>
и <unistd.h>
соответственно).
Тем не менее, предпочтительный способ C++ - это оборачивать дескриптор в объект с тысячами членов, чтобы делать все.
Я использую boost::filesystem::ifstream
(или ofstream
для письма).
На самом деле я спрашивал об этом, потому что хотел быть уверенным, что мой файл был закрыт, даже если перед вызовом file.close()
возникло исключение.
Но после прочтения документации еще раз:
В случае уничтожения объекта, все еще связанного с открытым файлом, деструктор автоматически вызывает функцию-член close.
Так что это безопасно :)
std::fstream
? - person DevSolar   schedule 01.04.2014FILE*
. Что это значит для вас? - person Mark Ransom   schedule 22.10.2017HANDLE
, как в msdn.microsoft.com/en-us/library/windows/desktop/ - person Dev Null   schedule 22.10.2017