我想编写一个可以选择接受 lambda 来自定义其行为的类方法。所以在使用这个类时,我想知道我是否需要担心 lambda 本身超出范围?
lambda 不会引用任何外部变量,所以我不担心变量的范围,只担心 lambda 本身的范围,我会在类中存储对它的引用。
我是否需要担心 lambda 本身的创建方式/位置?
References, outside of narrow situations, do not extend the lifetime of the thing you are referencing.
Using a reference to something whose lifetime has expired is undefined behavior.
The undefined behavior of a stateless lambda may be "I don't even use my this
pointer", so you may be fine. However, if you know that the lambda is going to be stateless, you could instead store a function pointer.
Now, your class, in order to store an actual lambda, must be templated on that lambda type. And if it is a stateless lambda, it is almost certainly going to be as small (or smaller) than a reference to that lambda. So why not just store a copy of the lambda?
If instead you are storing a std::function<void()>
or the like, that is not a reference to a lambda. That is a type erasure object that wraps a copy of a lambda. Storing a reference to a std::function<void()>
after it goes out of scope would be a bad idea, as it is not stateless, and will go off and read garbage memory when you try to invoke it.
可能无法完全填写您的答案,但看看 Herb sutter 如何使用 lambdas 解决方案解决了类似的 RAII。另请参阅此SO 问题
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。您不应持有对 lambda 的引用,因为函数本身将位于程序的只读部分中。lambda 保存的唯一数据是函数指针及其捕获。如果确实有捕获,则取决于 lambda 的范围,如果超出范围,您将访问已释放的内存。