Lambda 作为 std::vector::emplace_back 的参数

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

我遇到了将 lambda 作为参数传递给 emplace_back 的代码,这让我很困惑。所以我写了一个小测试来验证这样的语法:

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;
}

我有两个问题: 1) 有人可以阐明如何将 lambda 作为参数传递给 emplace_back 吗?过去我只看到构造函数参数被传递给 emplace。 2) 输出为:

constructed
moved
constructed
moved
copied

最后一份副本来自哪里?为什么这两种方法不等价。

注意 lambda 定义后的 (),它调用 lambda。此代码等效于以下内容:

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

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

    // ...
}

其中,由于 lambda 有空捕获,等同于:

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

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

    // ...
}

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

您没有传递 lambda。相反,您传递了调用 lambda 的 result

Where is the last copied coming from?

它来自向量。当a2插入到vec时,会发生重新分配,重新分配内存,将旧内存中的对象复制到新内存

如果将移动构造函数指定为noexcept,即

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

然后std::vector会在重新分配时移动对象而不是复制,你可以看到最后的复制变成了移动。