6

也许我想太多了,但请考虑以下示例:

bool some_state = false;

// ... later ...

some_state = true;
do_something();
some_state = false;

现在想象一下,do_something()可以扔。我们不会some_state回到false. 最好有某种自动堆栈,根据范围推送/弹出以记住以前的值:

{
    scoped_restore res( some_state, true ); // This sets some_state to true and remembers previous value (false)
    do_something();
} // At this point, res is destroyed and sets some_state back to false (previous value)

boost有这样的东西吗?我当然可以编写自己的对象,但我想确保我不会先重新发明轮子。我在 MSVC 上使用 C++03,所以很遗憾我不能使用任何花哨的新 C++11 :(

4

2 回答 2

1

Boost确实有这样的东西。它被称为 state_saver。它有点隐藏在序列化库中,但它已被记录并且显然是官方的(即不在某些详细的命名空间中)。

http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/state_saver.html

演示:http ://rextester.com/NVXUG70771

于 2016-06-17T17:01:02.137 回答
0

你在正确的树上吠叫。Bjarne Stroustrup 强烈建议将 RAII 用于异常处理,而不是 try/catch/finally。在最新一期的 The C++ Programming Language(第 4 版)中,他在第 13 章“异常处理”中完整地概述了他推荐的方法。

替换一整章是相当困难的,所以首先,我建议只阅读这一章。但是,基本思想是使用组合并让构造函数保护资源。

因此,如果您的 A 类可以保护 3 个可能每个都抛出的资源(可能是一些内存),那么您可以让子对象在其构造函数(而不是 A 的构造函数)中保护每个资源。关键是,如果允许构造函数完成,则(通过语言)保证将调用析构函数。因此,在顶级构造函数中初始化子对象,如下所示:

class B{

    public:

        B( int n )
        {
            //allocate memory (may throw)
        }

        void *secured_memory;

        ~B(){
            //release memory        
        }

}


class A{

    public:

        A( int n )
            :b{n}, c{n}, d{n}
        {
            //will not complete if B, C or D throws
            //but because the constructors of B and C completed
            //their destructors will be invoked if D throws         
        }

        B b;
        C c;
        D d;

}

想象一下存在 C 类和 D 类,并且它们的结构类似于 B。因此,在上面的示例中, some_state 将通过 B、C 或 D 之类的类来保护。

这里的另一个关键点。您应该只保护每个子对象类中的单个资源。这样,资源被获取并且构造函数被允许退出(从而确保析构函数被调用,这将安全地释放资源)或者它抛出(因此,不获取资源)。

于 2013-07-24T04:28:57.583 回答