【发布时间】:2020-02-22 05:32:14
【问题描述】:
智能指针对我来说是一个新概念。我一直在尝试使用带有自定义删除器(unique_ptr)的智能指针围绕 fopen_s 和 fclose 包装一个 File 类。
以下是我的尝试。它成功编译、运行并生成了一个名为“text.txt”的文件,其内容为“Hello World”。
我不得不在我的 Open 函数中使用“new”来初始化 unique_ptr,因为 make_unique 似乎不适用于自定义删除器。由于我使用的是“新”,因此我的自定义删除器负责释放分配的内存吗?
我已经完成了我的程序 (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;
}
【问题讨论】:
-
哇,这很复杂。而
s_handle_map_似乎除了创建悬空手柄之外没有其他用途。 -
为什么要用
new分配一些东西?文件句柄是打开和关闭的,而不是分配和释放的。 -
由于您手动且显式地使用
delete,您未能将资源清理委托给智能指针。 -
Windows 有一个
HANDLE类型,但Handle是什么?std::move(handle)可能不会像你认为的那样做 -
@rustyx
fclose()是关闭和释放FILE结构的正确方法
标签: c++ c++11 unique-ptr