Assigning local lambda makes for dangling reference?

Hi,

I have a local lambda that is assigned to a field of an object called storage. This lambda will be called from elsewhere and my concern is whether this lambda is a dangling reference... isn't it destroyed when the function in which it is defined is exited?

Like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
auto& Storage::get_storage()
{
     static auto storage = make_storage( //..........);

     	storage.on_open = [](sqlite3* db)                  // LAMBDA
	{
		static const char* key = "another";
		static int keylen = 7;

		sqlite3_key(db, key, keylen);
	};
      return storage;
}


Is the LAMBDA code destroyed on function exit? Later when storage.on_open is called, is it calling a dangling lambda?

You see my concern?

Thanks,
Juan
Last edited on
¿why would storage.on_open be destroyed?
however, each call to get_storage() does overwrite .on_open with another lambda.
not storage.on_open but rather its value (the lambda) which is destroyed at function get_storage() exit!! storage.on_open would be pointing to an automatic local lambda which is destroyed at function exit!

You are also correct it is assigned with a new lambda each time.. but my question is is the lambda destroyed on function exit? since after all the lambda is a local object...
Last edited on
> but my question is is the lambda destroyed on function exit? since after all the lambda is a local object...

The closure object is move assigned to storage.on_open; it does not matter that the life-time of the moved from object would end at function exit.
Is the LAMBDA code destroyed on function exit?
Of course not. A lambda function is a function like any other. The difference is the way to access that function. The information how to access the lambda function is stored in a kind of structure. You create an object from these structure and it behaves like any other object. So when you have no object regarding the lambda you cannot call it anymore.

The lambda function itself runs as long as it runs. Regardless whether its access object still exists or not. Or any other object that matters.
A lambda expression, when evaluated, results in a function object (the closure object); an object of a class type with an implicitly declared (possibly trivial) destructor.
The closure object is destroyed when its logical life-time ends.

A lambda-expression provides a concise way to create a simple function object.
A lambda-expression is a prvalue whose result object is called the closure object.
https://eel.is/c++draft/expr.prim.lambda#general-1

The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type...
https://eel.is/c++draft/expr.prim.lambda.closure#1

The closure type associated with a lambda-expression has an implicitly-declared destructor
https://eel.is/c++draft/expr.prim.lambda.closure#15
>The closure object is move assigned to storage.on_open; it does not matter that the life-time of the moved from object would end at function exit.

storage.on_open is a field of type std::function<void(sqlite3*)> of an object. How do I know it is moved assigned?
I looked at the implementation of std::function and found something answering my own question:

1
2
3
4
template <class _Fx, typename _Mybase::template _Enable_if_callable_t<_Fx&, function> = 0>
function(_Fx _Func) {
    this->_Reset(_STD move(_Func));
}



Is this why?
> How do I know it is moved assigned?

The standard specifies that std::function<> stores a copy of the CopyConstructible Callable target. (Uses dynamically allocated memory to hold the copy, except for small targets).

Note: we can use std::reference_wrapper to wrap a reference to a callable object;
"If the stored reference is Callable, std::reference_wrapper is callable with the same arguments."
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
Topic archived. No new replies allowed.