Copy of functor and initializer_list

I'm a little confused about what happens when copying functors and / or initializers. In the following code, I thought that I would copy / move objects all the time, but without it Segfaults. I seem to be doing something wrong, but have not yet understood what my wrong assumptions are. Strange at cppreference.com I couldn't find a copy or move constructor for initializer_list , so I wonder what actually happens in these cases.

 #include <string> #include <vector> #include <functional> #include <iostream> std::initializer_list<std::function<std::string()>> getInitializer() { return { []() -> std::string { return "If"; } }; } int main() { std::function<int(std::string)> func; { auto init = getInitializer(); func = [init](std::string text) -> int { std::vector<std::function<std::string()>> vec(init); for( auto& el : vec ) { std::cout << el(); } std::cout << text << std::endl; return 5; }; } return func(" you see this - the world is all right!"); } 
+4
source share
1 answer

I don't have much experience with initializer_list s, but the standard seems to suggest that the initializer_list implementation looks like a pair of pointers to an array. The list in getInitializer has an automatic lifetime, as well as an array that supports it. You end up returning a pair of pointers to an array that no longer exists.

The relevant sections of the standard are 8.5.4 [decl.init.list] clauses 5 and 6:

5.- An object of type std::initializer_list<E> is created from the list of initializers, as if the implementation allocated an array of N elements of type E , where N is the number of elements in the list of initializers. Each element of this array is initialized with a copy with the corresponding element in the list of initializers, and the std::initializer_list<E> object is created to access this array. If the initialization of any element requires a narrowing of the transformation, the program is poorly formed.

6.- The lifetime of the array is the same as that of the initializer_list object.


So, for your specific case, the implementation will be roughly equivalent to this:

 std::initializer_list<std::function<std::string()>> getInitializer() { std::function<std::string()> __a[1] = { []() -> std::string { return "If"; } }; return std::initializer_list<std::function<std::string()>>(__a, __a+1); } 
+7
source

All Articles