Умные указатели - это новая концепция для меня. Я пытался обернуть класс File вокруг fopen_s и fclose, используя умный указатель с пользовательским средством удаления (unique_ptr).
Ниже приведена моя попытка. Он успешно компилирует, запускает и генерирует файл с именем «text.txt» с содержимым «Hello World», как и ожидалось.
Мне пришлось использовать «new» для инициализации unique_ptr в моей функции Open, поскольку make_unique не делаетПоявится работа с пользовательскими удалителями. Так как я использую «new», отвечает ли мой пользовательский инструмент удаления за освобождение выделенной памяти?
Я прошел программу (VS2019). File :: Close вызывается только один раз. Я ожидал, что он будет вызван, когда «дескриптор» в моей функции File: Open вышел из области видимости, но это был не тот случай. На это поведение может повлиять вызов std :: move (). Не уверен, как исследовать дальше, что здесь происходит.
#include <Windows.h>
#include <memory>
#include <string>
#include <map>
class File
{
private:
//functors - custom deleter
struct Close { void operator()(FILE** _handle); };
//type definitions
typedef std::unique_ptr<FILE*,File::Close> Handle;
typedef std::map<std::string,Handle> HandleMap;
//static members
static Handle& Open(std::string _name, std::string _mode);
static HandleMap s_handle_map_;
//variables
Handle& handle_;
std::string name_;
public:
//functions
File(std::string _name, std::string _mode);
void Write(std::string _message);
};
File::HandleMap File::s_handle_map_;
File::File(std::string _name, std::string _mode)
:handle_(Open(_name,_mode)),
name_(_name)
{
}
File::Handle& File::Open(std::string _name, std::string _mode)
{
bool exist = s_handle_map_.count(_name) > 0;
if (!exist)
{
Handle handle(new FILE*(nullptr));
//open new file
fopen_s(
handle.get(),
_name.c_str(),
_mode.c_str()
);
//transfer ownership of handle
s_handle_map_.emplace(
_name,
std::move(handle)
);
}
return s_handle_map_[_name];
}
void File::Close::operator()(FILE** _handle)
{
fclose(*_handle);
*_handle = nullptr;
//necessary?
delete _handle;
_handle = nullptr;
}
void File::Write(std::string _message)
{
fprintf(*handle_, _message.c_str());
}
int WINAPI WinMain(HINSTANCE _instance, HINSTANCE _previous, LPSTR _cmd, int _show)
{
File file("test.txt","w");
file.Write("Hello World\n");
return 0;
}