简体   繁体   中英

Lambda as an argument to std::vector::emplace_back

I came across code that passes a lambda as an argument to emplace_back, which confused me. So I wrote a small test to validate the syntax like this:

struct A
{
    int a;
    A(){cout<<"constructed"<<endl;}
    A(const A& other){a = other.a; cout<<"copied"<<endl;}
    A(const A&& other){a = other.a; cout<<"moved"<<endl;}
};

int main()
{
   vector<A> vec;
   vec.emplace_back(
       []{A a;
       a.a = 1;
       return a;   
       }());

   A a2;
   a2.a = 2;
   vec.emplace_back(std::move(a2));

  return 0;
}

I have two questions: 1) Can someone clarify how a lambda can be passed as an argument to emplace_back? I had only seen constructor arguments being passed to emplace back in the past. 2) The output was:

constructed
moved
constructed
moved
copied

Where is the last copied coming from? Why aren't the two approaches equivalent.

Can someone clarify how a lambda can be passed as an argument to emplace_back?

You are not passing a lambda. Instead, you pass the result of calling the lambda.

Where is the last copied coming from?

It comes from the vector. When a2 is inserted to vec , a reallocation occurs, which reallocates memory and copy the objects in the old memory to the new memory.

If you specify the move constructor as noexcept , ie

A(const A&& other) noexcept {a = other.a; cout<<"moved"<<endl;}

then std::vector will move the objects during reallocation instead of copying, and you can see the last copy becomes move.

Notice the () after the lambda definition, which calls the lambda. This code is equivalent to the following:

int main()
{
    auto make_a = []()
    {
        A a;
        a.a = 1;
        return a;
    };

    vector<A> vec;
    vec.emplace_back(make_a());

    // ...
}

Which, since the lambda has empty capture, is equivalent to this:

A make_a()
{
    A a;
    a.a = 1;
    return a;
}

int main()
{
    vector<A> vec;
    vec.emplace_back(make_a());

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM