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

时间:2018-04-27 16:55:08

标签: c++ stl stdvector

我遇到了将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

最后复制的来自哪里?为什么两种方法不等同。

2 个答案:

答案 0 :(得分:3)

  

有人可以澄清一下lambda如何作为emplace_back的参数传递?

你没有传递lambda。相反,您传递了调用lambda的结果

  

最后复制的来自哪里?

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

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

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

然后std::vector将在重新分配期间移动对象而不是复制,您可以看到最后一个副本移动。

答案 1 :(得分:1)

注意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());

    // ...
}