c++ 为什么在lambda的捕获列表中调用复制构造函数

lx0bsm1f  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(348)
#include <iostream>
#include <vector>
#include <functional>

using namespace std;

struct B {
    B() {
        std::cout<<"B"<<std::endl;
    }
    
    B(B&& b2) {
        std::cout << "B&& from object moved" << b2.moved_ << std::endl;
        b2.moved_ = true;
    }
    
    B(const B&) {
        std::cout<<"const B&"<<std::endl;
    }
    
    // ~B(){
    //     std::cout<<"~B"<<std::endl;
    // }
    
    int bb=10;
    bool moved_=false;
};

struct FF {
    FF(std::function<void()> ff):ff_(std::move(ff)){}
    std::function<void()> ff_;
};

int main()
{
    std::vector<int> a{1,2,3};
    std::vector<FF> b{};
    B bb;
    std::transform(a.cbegin(), a.cend(), std::back_inserter(b), [x = std::move(bb)](auto const i) {
        
        return FF([xx = std::move(x), i]() {
            std::cout<<"FF"<<i<<std::endl;
        });
    });
    
    for(auto const& j:b) {
      j.ff_();
    }
    return 0;
}

字符串
从代码中可以看出,我的容器B是FF的一个向量,它接受一个函数对象作为参数。我想确认lambda如何捕获参数。
我的问题是为什么const& constructor会在捕获列表中xx=std::move(x)时被调用?
我认为不应该有额外的建设者。

owfi6suc

owfi6suc1#

这是因为lambda不是可变的,包含了不能移动的const B x
容易修复

[x = std::move(bb)](auto const i) mutable {

字符串

bttbmeg0

bttbmeg02#

由于外部lambda没有标记为可变的,因此捕获xstd::move(x)中的const,即返回类型是B const&&,而不是B&&。但是,您的移动构造函数不能接受B const&&,而是使用复制构造函数。
mutable添加到外部lambda解决了这个问题:

std::transform(a.cbegin(),a.cend(),std::back_inserter(b),
    [x = std::move(bb)](auto const i) mutable { // mutable added here
        return FF([xx = std::move(x),i](){
             std::cout<<"FF"<<i<<std::endl;
        });
    });

字符串

相关问题