Reputation: 392
This is just theoretical question. When i execute this code:
#include <functional>
#include <cstdio>
struct A {
int value = 100;
A() {
printf("A\n");
}
A(const A& a) {
printf("copy A\n");
}
~A() {
printf("~A\n");
}
};
void function(std::function<int()> lambda) {
printf("%d\n", lambda());
}
int main()
{
A a;
auto lambda = [a]() -> int {
return a.value;
};
function(lambda);
return 0;
}
Output is this:
A
copy A
copy A
copy A
100
~A
~A
~A
~A
And my question is why struct A is copied 3 times, not 2? One copy takes lambda capture, second takes passing argument to function and third takes what?
Upvotes: 4
Views: 217
Reputation: 50024
You will see the same number of copy operations, if you change your code as follows:
int main()
{
A a;
auto&& lambda = [a]() -> int {
return a.value;
};
std::function<int()>{lambda};
}
The first copy/move construction occurs when creating the lambda. The second and third copy/move constructions happen during construction of the std::function. According to N3690, the used constructor of std::function looks as follows:
template <class F> function(F);
That means, the passed argument will be copied/moved once when passing the argument to the constructor. Within the constructor, it will be copied/moved another time for type erasure.
If the constructor would use references instead (e.g. with perfect forwarding), you would only see two copy/move constructions. However, I don't know why it wasn't used in this case.
template <typename Arg> function(Arg&&);
Upvotes: 2