AdUki
AdUki

Reputation: 392

C++ lambdas passing

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

Answers (1)

nosid
nosid

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

Related Questions