boost或C++ 0x中的任何RAII模板

Yog*_*ora 14 c++ templates boost raii c++11

在boost中是否有可用的模板RAII.有像这样的类scoped_ptr,shared_ptr它基本上用于指针.这些类可以用于除指针之外的任何其他资源.是否有任何模板可以使用一般资源.

例如,在范围的开头获取的某些资源必须以某种方式在范围的末尾发布.获取和发布都需要一些步骤.我们可以编写一个模板,它需要两个(或者一个对象)仿函数来完成这个任务.我还没有想过如何实现这一点,我只是想知道有没有现成的方法来做到这一点

Edit: 如何在C++ 0x中支持lambda函数

sth*_*sth 12

shared_ptr提供了指定自定义删除器的可能性.当需要销毁指针时,将调用删除器并可以执行任何必要的清理操作.这样,使用此智能指针类可以管理比简单指针更复杂的资源.

  • 自定义删除器很棒,但是如果您想要管理的类型不是指针呢?当包装像`example_t data一样使用的C库时,这种情况发生了很多.example_new(数据);/*操纵数据...*/example_free(&data)`,如果这些对象存储在某个持久容器中,那么你也必须存储托管指针,这将是不切实际和浪费的. (2认同)

Geo*_*che 8

最通用的方法是ScopeGuard方法(本ddj文章中的基本思想,例如在Boost.ScopeExit中使用便利宏实现),并允许您在范围出口处执行函数或清理资源.

但说实话,我不明白为什么你会这么想.虽然我理解每次为一步一步和一步发布模式编写一个类有点烦人,但你在谈论多步获取和释放.
如果它采取了多个步骤,在我看来,它属于一个适当命名的实用程序类,以便隐藏细节并使代码到位(从而降低错误概率).
如果你将它与收益进行权衡,那些额外的几行就不用担心了.

  • @ pm100:不,你已经把它颠倒了.最后意味着我每次使用该类时都必须编写清理代码.RAII,依赖于析构函数,意味着我可以每个类编写一次清理代码*.最后怎么样一个好主意呢? (16认同)
  • 说实话,我很少觉得OP需要提到什么,因为每个重复的资源使用模式*都应该在实用程序类中.添加奖金 - 您不必记住资源处理细节. (3认同)
  • 当你*希望*编写仅在一个地方发生的清理代码并且在同一资源的不同用户之间不一致时,最后是个好主意.即,从不.不,我的意思是:例如,当您想要为某些事物添加一些快速跟踪,或者编写一个事务(几乎总是唯一的并且仅在一个地方使用)时.显然你可以编写一个代表你的交易的类,但如果你*有*那么它可以得到一点企业y,因此各种范围保护,这是好的(更好,甚至),除非你已经习惯了最后和对学习编码风格感到不舒服. (3认同)
  • @jalf:阿门!终于是可憎的! (2认同)

Buğ*_*dik 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_;
};
Run Code Online (Sandbox Code Playgroud)

使用示例:

RAIIFunc<int (int), ::close> f = ::open("...");
Run Code Online (Sandbox Code Playgroud)


jal*_*alf 5

我必须承认我并不真正明白这一点。从头开始编写RAII包装器已经非常简单。使用某种预定义的包装程序可以节省很多工作:

struct scoped_foo : private boost::noncopyable {
  scoped_foo() : f(...) {}
  ~scoped_foo() {...}

  foo& get_foo() { return f; }

private:
  foo f;
};
Run Code Online (Sandbox Code Playgroud)

现在,...如果您使用某种通用的RAII模板,则本质上是必须手动填写的位:创建和销毁我们的foo资源。没有它们,实际上剩下的还很少。几行样板代码,但是它是如此之少,以至于将其提取到可重用的模板中似乎并不值得,至少目前还不行。在加入C ++ 0x中的lambda表达式,我们可以写为创建和销毁函子如此简洁,这可能是值得写的,并将其插入可重复使用的模板。但是直到那时,看来麻烦多于价值。如果要定义两个函子以插入RAII模板,则您已经编写了大部分样板代码两次


Lie*_*yan 5

我在想类似的事情:

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);
        }
};
Run Code Online (Sandbox Code Playgroud)

并以此方式使用(以OpenGL的GLUquadric为例):

RAII<GLUquadric*> quad = RAII<GLUquadric*>(gluNewQuadric, gluDeleteQuadric);
gluSphere(quad.value, 3, 20, 20)
Run Code Online (Sandbox Code Playgroud)