gpt4 book ai didi

c++ - 依靠 Windows 句柄的类型作为指针可以吗?

转载 作者:可可西里 更新时间:2023-11-01 14:45:08 25 4
gpt4 key购买 nike

Windows 句柄有时很烦人,要记得在之后进行清理(使用创建的笔和画笔进行 GDI 就是一个很好的例子)。 RAII 解决方案很棒,但是为每种不同类型的 handle 制作一个完整的(五法则)RAII 类真的那么好吗?当然不是!我能看到的最好的是一个完整的通用 RAII 类,其他类只定义应该清理句柄时要做什么,以及其他特定于句柄的方面。

例如,一个非常简单的模块类可以这样定义(只是一个例子):

struct Module {
Module() : handle_{nullptr} {}
Module(HMODULE hm) : handle_{hm, [](HMODULE h){FreeLibrary(h);}} {}
operator HMODULE() const {return handle_.get();}

private:
Handle<HMODULE> handle_;
};

一切都很好,花花公子,不需要析构函数或任何东西。当然,能够将 Handle 类编写为不需要析构函数或其他任何东西也很好。为什么不使用现有的 RAII 技术?一种想法是使用指向 void 的智能指针,但这行不通。以下是正常情况下实际声明句柄的方式:

#define DECLARE_HANDLE(n) typedef struct n##__{int i;}*n
DECLARE_HANDLE(HACCEL);
DECLARE_HANDLE(HBITMAP);
DECLARE_HANDLE(HBRUSH);
...

它实际上区分句柄类型,这很好,但它使得使用指向 void 的智能指针变得不可能。相反,如果根据定义,句柄是指针,那么可以提取类型怎么办?

我的问题是以下假设是否安全。它使用必须关闭的桌面句柄。除了共享指针和唯一指针之间的差异(例如,FreeLibrary 有其自己的引用计数语义),假设句柄是一个指针并将智能指针指向它指向的任何内容,或者我不应该使用智能指针并使 Handle 本身实现 RAII 方面?

#include <memory>
#include <type_traits>
#include <utility>
#include <windows.h>

int main() {
using underlying_type = std::common_type<decltype(*std::declval<HDESK>())>::type;
std::shared_ptr<underlying_type> ptr{nullptr, [](HDESK desk){CloseDesktop(desk);}};
}

最佳答案

我相信所有 Windows 指针在技术上都是指向系统 Windows 内核部分内部对象的指针(或者有时,可能是指向由内核代码分配的用户端对象,或该主题的某些变体)。

我完全不相信您应该将它们视为指针。它们只是纯技术角度的指针。它们不再是“指针”,就像 C 风格的“FILE *”是指针一样。我不认为你会建议使用 shared_ptr<FILE*>稍后处理关闭文件。

将句柄包装到稍后清理它的东西中绝对是个好主意,但我认为使用智能指针解决方案不是正确的解决方案。使用知道如何关闭 handle 的模板化系统将是理想的。

我想您还需要以某种适用于所有相关人员的好方法处理“我想将此句柄从这里传递到其他地方” - 例如你有一个以某种方式获取资源的函数,它返回这些资源的句柄——你是否返回一个已经包装的对象,如果是,拷贝如何工作?

如果您需要在使用另一个 handle 之前保存一个 handle 的拷贝(例如,保存当前笔,然后设置自定义笔,然后恢复)怎么办?

关于c++ - 依靠 Windows 句柄的类型作为指针可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16676701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com