RAII
的提升中是否有可用的模板。像scoped_ptr
,shared_ptr
这样的类基本上适用于指针。这些类可以用于除指针之外的任何其他资源。是否有任何适用于一般资源的模板。
例如,在范围的开头获取的某些资源必须以某种方式在范围的末尾发布。获取和发布都需要一些步骤。我们可以编写一个模板,它需要两个(或者一个对象)仿函数来完成这个任务。我还没有想过如何实现这一点,我只是想知道有没有现成的方法来做到这一点
Edit:
如何在C ++ 0x中支持lambda函数
答案 0 :(得分:12)
shared_ptr
可以指定custom deleter。当需要销毁指针时,将调用删除器并可以执行任何必要的清理操作。这样,可以使用此智能指针类来管理比简单指针更复杂的资源。
答案 1 :(得分:8)
更通用,更高效(不通过函数指针调用)版本如下:
#include <boost/type_traits.hpp>
template<typename FuncType, FuncType * Func>
class RAIIFunc
{
public:
typedef typename boost::function_traits<FuncType>::arg1_type arg_type;
RAIIFunc(arg_type p) : p_(p) {}
~RAIIFunc() { Func(p_); }
arg_type & getValue() { return p_; }
arg_type const & getValue() const { return p_; }
private:
arg_type p_;
};
使用示例:
RAIIFunc<int (int), ::close> f = ::open("...");
答案 2 :(得分:7)
最通用的方法是ScopeGuard方法(this ddj article中的基本思想,例如在Boost.ScopeExit中使用便捷宏实现),并允许您在范围出口处执行函数或清理资源
但说实话,我不明白为什么你会这么想。虽然我理解每次为一步一步和一步释放模式编写一个类有点烦人,但你在谈论多步获取和释放。
如果它采取了多个步骤,在我看来,它属于一个适当命名的实用程序类,以便隐藏细节并使代码到位(从而降低错误概率)。
如果你把它与收益进行权衡,那些额外的几行就不用担心了。
答案 3 :(得分:5)
我不得不承认我没有看到这一点。从头开始编写RAII包装器已经非常简单了。使用某种预定义的包装器可以节省很多工作:
struct scoped_foo : private boost::noncopyable {
scoped_foo() : f(...) {}
~scoped_foo() {...}
foo& get_foo() { return f; }
private:
foo f;
};
现在,如果您使用某种通用RAII模板,...
本质上是必须手动填写的位:创建和销毁我们的foo
资源。没有他们,真的没有多少剩下。几行样板代码,但它很少似乎不值得将它提取到一个可重用的模板,至少目前不是。通过在C ++ 0x中添加lambdas,我们可以编写用于创建和销毁的仿函数,这样简洁,可能值得编写并将它们插入可重用模板。但在那之前,它似乎比值得更麻烦。如果您要定义两个函子来插入RAII模板,那么您已经编写了大部分样板代码两次。
答案 4 :(得分:4)
我在想类似的东西:
template <typename T>
class RAII {
private:
T (*constructor)();
void (*destructor)(T);
public:
T value;
RAII(T (*constructor)(), void (*destructor)(T)) :
constructor(constructor),
destructor(destructor) {
value = constructor();
}
~RAII() {
destructor(value);
}
};
并像这样使用(以OpenGL的GLUquadric为例):
RAII<GLUquadric*> quad = RAII<GLUquadric*>(gluNewQuadric, gluDeleteQuadric);
gluSphere(quad.value, 3, 20, 20)
答案 5 :(得分:3)
这是另一个C ++ 11 RAII助手:https://github.com/ArtemGr/libglim/blob/master/raii.hpp
它在销毁时运行C ++仿函数:
auto unmap = raiiFun ([&]() {munmap (fd, size);});