【问题标题】:try catch finally construct - is it in C++11? [duplicate]try catch finally 构造 - 它在 C++11 中吗? [复制]
【发布时间】:2011-12-08 10:37:13
【问题描述】:

可能重复:
Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?)

C++11 是否支持 try/catch/finally 构造?
我问是因为我找不到任何有关它的信息。 谢谢。

【问题讨论】:

  • 就其价值而言,在我看来,RAII 的问题在于它强烈限制了您的类层次结构设计。在某些情况下,您想整理但自然没有可用的课程来强制整理。
  • @David Heffernan,幸运的是,有了 lambda,使用范围保护比以往任何时候都容易。 :)
  • 正如其他人所说,C++11不直接支持finally关键字。但是,可以无缝地实施和使用它。在这里查看我的答案:stackoverflow.com/a/38701485/566849
  • 查看我的 try-finally 语句模仿版本:stackoverflow.com/a/47574378/5447906

标签: c++ c++11


【解决方案1】:

不是放弃 RAII 的借口,但在例如使用不支持 RAII 的 API:

template<typename Functor>
struct finally_guard {
    finally_guard(Functor f)
        : functor(std::move(f))
        , active(true)
    {}

    finally_guard(finally_guard&& other)
        : functor(std::move(other.functor))
        , active(other.active)
    { other.active = false; }

    finally_guard& operator=(finally_guard&&) = delete;

    ~finally_guard()
    {
        if(active)
            functor();
    }

    Functor functor;
    bool active;
};

template<typename F>
finally_guard<typename std::decay<F>::type>
finally(F&& f)
{
    return { std::forward<F>(f) };
}

用法:

auto resource = /* acquire */;
auto guard = finally([&resource] { /* cleanup */ });
// using just
// finally([&resource] { /* cleanup */ });
// is wrong, as usual

如果您不需要翻译或以其他方式处理异常,请注意如何不需要 try 块。

虽然我的示例使用了 C++11 功能,但 C++03 也提供了相同的通用功能(但没有 lambda)。

【讨论】:

  • 如何保证析构函数不会被调用两次?
  • @MrSamuel 很好。这确实需要一个标志来检查 *this 的当前状态(例如,移出的对象将被停用)。我确实在我的实际代码中修复了它,我正在更新这个答案。
  • 这是否按预期得到优化?例如支票会被删除吗?
  • @MrSamuel 无法提前告知。完全避免该标志的唯一方法是使用对临时对象的绑定:finally_guard&lt;typename std::decay&lt;decltype(functor)&gt;::type&gt;&amp;&amp; guard = { std::move(functor) };。这正是一种结构。它不能重构为函数(通过函数获取值意味着构造或返回没有生命周期扩展的悬空引用),但可以重构为宏。但是,由于decltype,这不适用于 lambda 表达式。所以你不可能全赢。
【解决方案2】:

C++11 不添加对finally 的支持。决策者(尤其是Stroustrup)多年来一直表示偏爱其他成语,即 RAII。我认为 C++ 极不可能包含finally

【讨论】:

    【解决方案3】:

    在 C++ 中你不需要 finally,因为 C++ 有 RAII 更好。

    【讨论】:

    • 但 RAII 并不总是 == 最终。
    • 你不能通过提供一个完整的疯狂的 sn-p 来真正表明 final 的需要:p。
    • 我不认为这很疯狂。它清楚地表明,在某些情况下,根据错误需要不同的方法,最后是一种干净的方法。而且它不能用 RAII 干净地完成
    • @smallB:它可以:scoped_ptr&lt;some_struct&gt; v = new some_struct; load_vector(v);。如果load_vector 抛出,您将不会在v 中泄漏内存。完成(+ 代码更具可读性)。
    • 投反对票,一个例子表示赞赏。
    猜你喜欢
    • 2014-11-27
    • 2016-03-28
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多