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

发布于 2024-08-18 16:31:21 字数 327 浏览 8 评论 0原文

boost 中是否有适用于 RAII 的模板。有像 scoped_ptrshared_ptr 这样的类基本上工作在指针上。这些类可以用于指针以外的任何其他资源吗?是否有任何适用于通用资源的模板。

以在作用域开始时获取的某些资源为例,必须在作用域结束时以某种方式释放该资源。获取和释放都需要一些步骤。我们可以编写一个模板,它需要两个(或者可能是一个对象)函子来完成这项任务。我还没有考虑如何实现这一点,我只是想知道是否有现有的方法可以做到这一点

编辑: C++0x 中支持 lambda 函数的方法怎么样

Is there any template available in boost for RAII. There are classes like scoped_ptr, shared_ptr which basically work on pointer. Can those classes be used for any other resources other than pointers. Is there any template which works with a general resources.

Take for example some resource which is acquired in the beginning of a scope and has to be somehow released at the end of scope. Both acquire and release take some steps. We could write a template which takes two(or maybe one object) functors which do this task. I havent thought it through how this can be achieved, i was just wondering are there any existing methods to do it

Edit: How about one in C++0x with support for lambda functions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

请你别敷衍 2024-08-25 16:31:22

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

shared_ptr provides the possibility to specify a custom deleter. When the pointer needs to be destroyed, the deleter will be invoked and can do whatever cleanup actions are necessary. This way more complicated resources than simple pointers can be managed with this smart pointer class.

萌无敌 2024-08-25 16:31:22

最通用的方法是 ScopeGuard 之一(基本思想在 这篇 ddj 文章,例如在 Boost.ScopeExit),并允许您在范围退出时执行函数或清理资源。

但说实话,我不明白你为什么想要这样。虽然我知道每次为一步获取和一步释放模式编写一个类有点烦人,但您正在谈论多步获取和释放。
如果它采取多个步骤,在我看来,它属于一个适当命名的实用程序类,以便隐藏细节并就位代码(从而减少错误概率)。
如果你权衡收益,那几条额外的线并不是真正值得担心的事情。

The most generic approach is the ScopeGuard one (basic idea in this ddj article, implemented e.g. with convenience macros in Boost.ScopeExit), and lets you execute functions or clean up resources at scope exit.

But to be honest, i don't see why you'd want that. While i understand that its a bit annoying to write a class every time for a one-step-aquire and one-step-release pattern, you are talking about multi-step-aquire and -release.
If its taken multiple steps, it, in my opinion, belongs in an appropiately named utility class so that the details are hidden and the code in place (thus reducing error probability).
If you weigh it against the gains, those few additional lines are not really something to worry about.

暖风昔人 2024-08-25 16:31:22

更通用、更高效(不通过函数指针调用)的版本如下:

#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("...");

A more generic and more efficient (no call through function pointer) version is as follows:

#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_;
};

Example use:

RAIIFunc<int (int), ::close> f = ::open("...");
晒暮凉 2024-08-25 16:31:22

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

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

  foo& get_foo() { return f; }

private:
  foo f;
};

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

I have to admit I don't really see the point. Writing a RAII wrapper from scratch is ridiculously simple already. There's just not much work to be saved by using some kind of predefined wrapper:

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

  foo& get_foo() { return f; }

private:
  foo f;
};

Now, the ...'s are essentially the bits that'd have to be filled out manually if you used some kind of general RAII template: creation and destruction of our foo resource. And without them there's really not much left. A few lines of boilerplate code, but it's so little it just doesn't seem worth it to extract it into a reusable template, at least not at the moment. With the addition of lambdas in C++0x, we could write the functors for creation and destruction so concisely that it might be worth it to write those and plug them into a reusable template. But until then, it seems like it'd be more trouble than worth. If you were to define two functors to plug into a RAII template, you'd have already written most of this boilerplate code twice.

£冰雨忧蓝° 2024-08-25 16:31:22

我正在考虑类似的事情:

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)

I was thinking about something similar:

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);
        }
};

and to be used like this (using OpenGL's GLUquadric as an example):

RAII<GLUquadric*> quad = RAII<GLUquadric*>(gluNewQuadric, gluDeleteQuadric);
gluSphere(quad.value, 3, 20, 20)
北城半夏 2024-08-25 16:31:22

这是另一个 C++11 RAII 帮助器: https://github.com/ArtemGr /libglim/blob/master/raii.hpp

它在销毁时运行一个 C++ 仿函数:

auto unmap = raiiFun ([&]() {munmap (fd, size);});

Here's yet another C++11 RAII helper: https://github.com/ArtemGr/libglim/blob/master/raii.hpp

It runs a C++ functor at destruction:

auto unmap = raiiFun ([&]() {munmap (fd, size);});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文