【问题标题】:C++ : other one simple scope guard [duplicate]C ++:另一种简单的范围保护[重复]
【发布时间】:2015-08-10 17:17:41
【问题描述】:

让我们问一下这个简单的范围保护:

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

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

【问题讨论】:

  • 这可以编译吗?您正在为可变左值引用分配一个临时值。
  • 它会编译。首先,我用闭包值初始化变量FIN##l##clo。 (也许,复制省略在这里有点帮助)。然后将 FIN##l##clo 的引用分配给变量 FIN##l##fin 的字段 t
  • 啊,我明白了。在那种情况下,为什么不存储对象并直接初始化它呢?复制省略将确保没有多余的副本,并且您不会通过引用进行间接访问
  • 如果你告诉我怎么做,我会很高兴的。我还没有找到更简单的方法来对抗模板参数推导。
  • 好吧,我制作了依赖复制省略的简单版本stackoverflow.com/questions/31922693/…

标签: c++ exception-safety scopeguard


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    局部变量的破坏按其构造的相反顺序进行。

    这是一种更有效的方法,它不需要引用并使用复制省略来就地构造 lambda。

    (请注意,您可能需要考虑 [&] 而不是 [=],但这由您自己判断)

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

    【讨论】:

    • 这和我的版本几乎一样 stackoverflow.com/questions/31922693/… 但我认为在析构函数中依赖复制省略并不是一件好事(但可能是这样)。
    • 哦,谢谢指点[&amp;]!!!真的很有道理。
    • 析构函数期间没有复制省略。它发生在对make_finop_t() 的调用期间以及从make_finop_t() 返回时作为RVO(返回值优化) - c++11 为我们提供了完美的转发。
    • >> 在析构函数期间没有复制省略。
    • 如果-fno-elide-constructors 标志传递给编译器,它就会被复制(如@dyp 在melpon.org/wandbox/permlink/B73EuYYKGYFMnJtR 中显示的那样)
    猜你喜欢
    • 2022-11-24
    • 2011-01-06
    • 2011-10-24
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 2011-10-07
    相关资源
    最近更新 更多