C ++ 11 lambdas本身是否受到RAII自动释放的影响?

时间:2013-11-13 18:28:08

标签: c++ c++11 lambda raii

我想编写一个类方法,可以选择接受lambda来自定义它的行为。所以当使用这个类时,我想知道我是否需要担心lambda本身超出范围?

lambda不会引用任何外部变量,所以我不担心变量的范围,只关于lambda本身的范围,我将在类中存储引用。

我是否需要担心lambda本身的创建方式/位置?

2 个答案:

答案 0 :(得分:2)

在狭隘情况之外,引用不会延长您引用的东西的生命周期。

使用对生命周期已过期的内容的引用是未定义的行为。

无状态lambda的未定义行为可能是“我甚至不使用我的this指针”,所以你可能没事。但是,如果你知道lambda将是无状态的,你可以改为存储一个函数指针。

现在,为了存储实际的lambda,你的类必须在该lambda类型上进行模板化。如果它是一个无状态的lambda,它几乎肯定会比那个lambda的引用小(或更小)。那么为什么不只是存储lambda的副本?

如果您要存储std::function<void()>等,那么这不是对lambda的引用。这是一个包装lambda副本的类型擦除对象。在std::function<void()>超出范围后存储引用将是一个坏主意,因为它无状态,并且当您尝试调用它时将关闭并读取垃圾内存。

答案 1 :(得分:1)

可能没有完全填写你的答案,但看看草药sutter如何用lambdas解决方案解决了类似的RAII。另见SO Question

template <class T> class locker {
private:
  mutable T m_t; // Copies the lambda here.
  mutable std::mutex m_m;
public:
  locker( T t = T{} ) : m_t(t) {}
  template <typename F>
  auto operator()(F f) const -> decltype(f(m_t)) {
    std::lock_guard<mutex> _{m_m};
    return f(t);
  }
};


// usage 
locker<std::string> s;
s([](string &s) {
  s += "foobar";
  s += "barfoo";
});

关于这个例子的重要部分是Lambda被复制了。您不应该持有对lambdas的引用,因为函数本身将位于程序的只读部分。 lambda拥有的唯一数据是函数指针及其捕获。如果你确实有捕获,那么你依赖于lambda的范围,如果这个范围超出范围,你就会访问已经发布的内存。