C++ 如何使用C++;带Windows句柄的标准智能指针?
我想知道是否有一种方法可以将C++ 如何使用C++;带Windows句柄的标准智能指针?,c++,winapi,c++11,C++,Winapi,C++11,我想知道是否有一种方法可以将unique\u ptr与Windows句柄一起使用 我想用调用CloseHandle的特定handle\u策略替换std::default\u delete。问题是HANDLE被定义为void*unique\u ptr不会编译为sizeof(void)未定义 到目前为止,我只看到两种可能性: 为句柄创建一个包装类,并像这样使用它:unique\u ptr。这几乎使独特的\u ptr本身毫无用处 使用类似于unique\ptr的HANDLE特定智能指针类 你认为什么是
unique\u ptr
与Windows句柄一起使用
我想用调用CloseHandle
的特定handle\u策略替换std::default\u delete
。问题是HANDLE
被定义为void*
unique\u ptr
不会编译为sizeof(void)
未定义
到目前为止,我只看到两种可能性:
为句柄创建一个包装类,并像这样使用它:unique\u ptr
。这几乎使独特的\u ptr
本身毫无用处
使用类似于unique\ptr
的HANDLE
特定智能指针类
你认为什么是更好的选择?你有什么建议
这个问题可以扩展到COM IUnknown
指针-可以用任何标准智能指针替换CComPtr
吗?创建一个特定的智能指针类,不会花费很长时间。不要滥用图书馆课程。句柄语义与C++指针有很大的不同;首先,取消对句柄的引用毫无意义
使用自定义智能句柄类的另一个原因-NULL并不总是意味着一个空句柄。有时它是无效的\u HANDLE\u值,它不相同(实际上是-1)。您必须使用CloseHandle()
来“关闭”句柄,而不是使用delete
。一旦它们没有在其他地方打开,Windows将立即删除它们。因此,您可以编写一个调用CloseHandle()的包装器,而不是删除它。您还可以编写自己的smartpointer类,这可能会更好,因为不再需要包装器。您可以创建一个将释放句柄的Deleter类,而不是调用delete()
您可以在此中看到他们如何解决使用共享\u ptr删除数组的问题(unique\u ptr还有一个接收Delete类的构造函数)
这个问题可以扩展到COM IUnknown指针-can CComPtr
是否被任何标准智能指针所取代
对。您不需要专门化std::default\u deleter
,只需替换deleter类型
struct COMDeleter {
template<typename T> void operator()(T* ptr) {
ptr->Release();
}
};
unique_ptr<IUnknown, COMDeleter> ptr; // Works fine
struct-comdeter{
模板无效运算符()(T*ptr){
ptr->Release();
}
};
唯一的\u ptr ptr;//很好
同样的原则也适用于shared\u ptr
,事实上,对于HANDLE
,您可以使用自定义删除器键入您的unique\u ptr
struct handle_deleter
{
void operator()(void* handle)
{
if(handle != nullptr)
CloseHandle(handle);
}
};
typedef std::unique_ptr<void, handle_deleter> UniqueHandle_t;
UniqueHandle_t ptr(CreateFile(...));
struct handle\u deleter
{
void运算符()(void*句柄)
{
if(handle!=nullptr)
关闭手柄(手柄);
}
};
typedef std::unique_ptr UniqueHandle_t;
UniqueHandle_t ptr(CreateFile(…);
我不建议使用带句柄的智能指针
我建议你仔细看看
就我个人而言,我正在利用该提案的参考实现,而不是在这些情况下使用std::unique\u ptr
。另一种解决方案
std::unique_ptr< void, void(*)( HANDLE ) > uniqueHandle( file, []( HANDLE h ) { ::CloseHandle( h ); } );
std::unique_ptruniqueHandle(文件,[](句柄h){::CloseHandle(h);});
受亚历山大·德里切尔解决方案的启发,这里的篇幅更短
std::unique_ptr< HANDLE, decltype(&CloseHandle) > uniqueHandle( nullptr, CloseHandle );
std::unique_ptruniqueHandle(nullptr,CloseHandle);
在MSVC 2010工作。请注意,您需要在decltype()中为函数名指定“&”,以推断函数类型的指针。句柄并不总是使用CloseHandle()关闭,请注意。
例如,使用FindTextFile()打开的句柄必须由FindClose()关闭。这里有一个方便的小“自定义”我用来处理句柄。
C++17
是编译此文件所必需的。这个想法是从另一个SO帖子中提出来的,我只添加了std::remove\u pointer\t
,这样我就不必将void
作为自定义ptr
类型参数传递
定义
#include <type_traits>
#include <memory>
template<auto fn>
using deleter_from_fn = std::integral_constant<decltype( fn ), fn>;
template<typename T, auto fn>
using custom_ptr = std::unique_ptr<typename std::remove_pointer_t<T>, deleter_from_fn<fn>>;
#包括
#包括
模板
使用deleter_from_fn=std::integral_常量;
模板
使用custom_ptr=std::unique_ptr;
使用
custom_ptr<HANDLE, &CloseHandle> phandle{
CreateFileMapping( INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 1024, L"FileName" ) };
custom_ptr phandle{
CreateFileMapping(无效的\u句柄\u值,空ptr,页\u读写,0,1024,L“文件名”);
我编写了自己的设置句柄特定类,因为有些句柄需要CloseHandle()
而其他句柄需要不同的API特定函数,有些句柄在未赋值时设置为无效的句柄值,而其他句柄则设置为空值,等等。我为大部分工作编写了一组基类,然后使用自定义特征类来处理闭包和分配问题。-1用于错误地重新实现库类。它们是专门为这个功能设计的,这不是滥用。您将引入无意义的新错误和代码。+1用于识别指针和句柄是具有不同语义的不同事物。将句柄硬塞入智能指针类型会给您提供一系列对句柄没有实际意义的方法。
custom_ptr<HANDLE, &CloseHandle> phandle{
CreateFileMapping( INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 1024, L"FileName" ) };