【发布时间】:2013-02-14 00:39:03
【问题描述】:
这里有一篇文章讨论了一个名为Rule of Zero 的成语。
摘录如下:
class module {
public:
explicit module(std::wstring const& name)
: handle { ::LoadLibrary(name.c_str()), &::FreeLibrary } {}
// other module related functions go here
private:
using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;
module_handle handle;
};
它重用了unique_ptr RAII 功能,因此您无需关心实现令人生畏且冗长的五规则包装器。
以这种方式呈现(使用 unique_ptr 管理基于句柄的资源,这种方式),它对我来说看起来像是一个 hack,而不是它试图解决的最佳解决方案。隐含的假设太多:
- 可以对等并使用
#define(或typedef)HANDLE所建立的基本类型。对我来说,这应该是隐藏的知识,解决方案完全基于界面提供的内容:HANDLE。 - 句柄,可以是任何东西,它们不需要是指针类型。
我想使用这个成语,但在我偶然发现的许多情况下它都不够用。
这个以处理 RAII 为中心的包装器是否已经完成并可以在一些很酷的库中使用?每个人都在使用这样的工具,我不知道吗? (我认为拥有这样的工具不仅适用于一种,而且适用于多种类型的所有权)
编辑 1
这与特定于平台的资源句柄无关,例如,glGenLists 返回一种句柄,它是一个GLuint,你应该在它上面调用glDeleteLists。如前所述,资源句柄不需要是指针类型,也不应该假设这种假设。
编辑 2
零规则,在前一个示例中,通过使用现有工具unique_ptr,显示为句柄管理的一个很好的快捷方式。它需要的额外假设使其不足。正确的假设是你有一个 handle 并且你有一个 resource 破坏函数 来破坏 handle 给定的资源。句柄是void *,GLuint,不管怎样,都无关紧要,更糟糕的是,甚至不需要对等HANDLE 内部类型。为了管理句柄 RAII 的方式,如果成语告诉它有好处,并且不能应用于这种情况,我觉得它不好,最后使用给定的工具。
编辑 3
一个说明性的情况是,假设您负责使用新的第 3 方 C 库。它包含一个FooHandle create_foo() 和一个void destroy_foo(FooHandle)。所以你想,“让我们通过使用零规则来使用 FooHandle”。好的,您可以使用unique_ptr、unique_ptr 来满足您的要求? FooHandle 是指针吗?这样你就可以使用unique_ptr 到FooHandle 的未暴露 基本类型?是int?,这样您就可以直接使用它,还是更好地(重新)typedef@NicolBolas 在他的回答中所做的事情。对我来说,似乎很清楚,即使在如此微不足道的情况下,unique_ptr 已经显示出不适合管理资源句柄的理想。
免责声明:
我试图重新表述并更好地表达自己:
编辑 4
我找到了我正在寻找的东西,我已将其作为重新表述的问题的答案:https://stackoverflow.com/a/14902921。
【问题讨论】:
-
您未能说出成语不可用的情况。是的,这个“规则”是“已经完成”。它被称为现代 C++ 风格
-
事实上,winapi中的
HANDLE是void *。这永远不会改变,并在Windows Data Types文章中明确说明。我认为使用智能指针轻松使用 RAII 绝对没有问题。 -
这似乎比问题更咆哮。
-
您似乎混淆了零规则的概念(尝试重用资源管理类,这样您就不必编写新的类)与一些通用包装器的存在。列出的代码只是使用零规则的一个示例,它并没有声称能够处理任何可能的句柄类型。是否存在完全通用的句柄包装器?可能不会。
-
让我以文章作者的身份加入。我担心我没有让自己足够清楚。正如 GManNickG 所说,零规则的想法并不是说您将需要的所有所有权原语都已经编写好了。这个想法是所有权原语是唯一应该处理所有权的事情。如果没有适合您目标的原语,请务必编写一个。只是不要将所有权与其他职责混为一谈。这不是成语:它只是适用于特定关注点的单一职责原则。
标签: c++ c++11 raii unique-ptr