我应该使用C++中的哪个包装类进行自动资源管理?

Vil*_*lx- 15 c++ raii resource-management

我是C++业余爱好者.我正在编写一些Win32 API代码,并且有句柄和奇怪的复合分配对象.所以我想知道 - 是否有一些包装类可以使资源管理更容易?

例如,当我想加载一些数据时,我打开一个文件CreateFile()并得到一个HANDLE.当我完成它之后,我应该呼吁CloseHandle()它.但是对于任何相当复杂的加载函数,将会有许多可能的退出点,更不用说例外了.

因此,如果我可以将句柄包装在某种类型的包装类中会很好,它会CloseHandle()在执行一次离开范围后自动调用.更好的是 - 它可以进行一些引用计数,因此我可以将其传入和传出其他函数,并且只有在最后一个引用离开范围时它才会释放资源.

这个概念很简单 - 但标准库中有类似的东西吗?顺便说一下,我正在使用Visual Studio 2008,而且我不想附加像Boost这样的第三方框架.

jal*_*alf 11

写你自己的.它只有几行代码.这是一项非常简单的任务,提供通用的可重用版本是不值得的.

struct FileWrapper {
  FileWrapper(...) : h(CreateFile(...)) {}
  ~FileWrapper() { CloseHandle(h); }

private:
  HANDLE h;
};
Run Code Online (Sandbox Code Playgroud)

想想通用版本必须做什么:它必须是可参数化的,因此您可以指定任何一对函数,以及任何数量的参数.只是实例化这样的对象可能需要与上面的类定义一样多的代码行.

当然,C++ 0x可能会在添加lambda表达式时略微平衡.两个lambda表达式可以很容易地传递给一个通用的包装类,所以一旦C++ 0x支持,我们可能会看到这样一个通用的RAII类添加到Boost或其他东西.

但目前,只要您需要,就可以更轻松地自己动手.

至于添加引用计数,我建议反对它.引用计数很昂贵(突然你的句柄必须动态分配,并且必须在每个分配时保持引用计数器),并且很难做到正确.这是一个在线程环境中充满细微竞争条件的区域.

如果你确实需要引用计数,只需执行以下操作boost::shared_ptr<FileWrapper>:将自定义ad-hoc RAII类包装在一个shared_ptr.

  • 由于可以复制结构,因此代码很糟糕.请查看http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization (2认同)
  • @Kerido,也许,也许不是.它取决于您正在包装的资源的语义.我认为给jalf带来怀疑的好处是公平的,并假设发布的代码只是一个简单的说明性示例. (2认同)
  • 是的,如果您想要一个强大的解决方案,绝对应该防止复制.我把它留下来显示一个简短的实现(如果你不试图聪明并复制它就足够了).防止复制的一种简单方法是继承自`boost :: noncopyable`,但是,是的,将copy ctor和赋值运算符设为私有.但正如克里斯托所说,这只是为了说明.为了简洁,我故意省略了复制构造函数. (2认同)