C ++:另一个简单的范围保护

时间:2015-08-10 17:17:42

标签: c++ exception-safety scopeguard

让我们问一下这个简单的范围守卫:

template <class T>
struct finop_t {
    T& t;
    ~finop_t() { t(); }
};
#define FINALLY__(l, cl) \
    auto FIN ## l ## clo = cl; \
    finop_t<decltype(FIN ## l ## clo)> FIN ## l ## fin { FIN ## l ## clo}
#define FINALLY_(l, cl) FINALLY__(l, cl)
#define FINALLY(...) FINALLY_(__LINE__, ([=](){__VA_ARGS__}))

int main() {
    FINALLY( std::cout << "hello" << std::endl ; );
    std::cout << "one" << std::endl;
    FINALLY( std::cout << "world" << std::endl ; );
    std::cout << "second" << std::endl;
    return 0;
}

在这里依赖销毁令是否安全?即安全假设在lambda析构函数之前调用~finop_t()吗?

2 个答案:

答案 0 :(得分:2)

是的,这是安全的。宏将lambda存储在局部变量中。局部变量的销毁顺序是固定的(按照与构造相反的顺序)。因此可以保证在相应的lambda(~finop_t())析构函数之前调用FIN ## l ## clo析构函数。

答案 1 :(得分:2)

局部变量的破坏按其构造的逆序发生。

这是一种更有效的方法,它不需要引用,并使用copy-elision来就地构建lambda。

(注意,您可能需要考虑[&amp;]而不是[=],但这是由你来判断的)

#include <iostream>

template <class T>
struct finop_t {
    finop_t(T&& t) : t(std::forward<T>(t)) {}
    T t;
    ~finop_t() { t(); }
};

template<class F>
finop_t<F> make_finop_t(F&& f)
{
    return finop_t<F>(std::forward<F>(f));
}

#define FINALLY__(l, cl) \
auto FIN ## l ## fin = make_finop_t(cl);

#define FINALLY_(l, cl) FINALLY__(l, cl)
#define FINALLY(...) FINALLY_(__LINE__, ([=](){__VA_ARGS__}))

int main() {
    FINALLY( std::cout << "hello" << std::endl ; );
    std::cout << "one" << std::endl;
    FINALLY( std::cout << "world" << std::endl ; );
    std::cout << "second" << std::endl;
    return 0;
}