使用 lambda 表达式复制和移动构造函数的 C++

C++ copy and move constructors with lambda expressions

提问人:David Carpenter 提问时间:9/3/2022 更新时间:9/3/2022 访问量:85

问:

我在使用 C++ 复制和移动构造函数时遇到了一些奇怪的东西,在这里,当传递给 lambda 表达式时,复制和移动构造函数都会被执行。奇怪的是,当我将 lambda 的声明类型更改为或使用该函数时,我得到了预期的行为(仅限复制构造)。有谁明白这是为什么?(使用 clang 和 gcc 测试,而不是 msvc)autoregular_test

#include <iostream>
#include <iomanip>
#include <functional>

using namespace std;

struct Test {
    inline Test() {
        cout << setw(20) << "constructor ";
        PrintAddress();
    }

    Test(const Test&) {
        cout << setw(20) << "copy constructor ";
        PrintAddress();
    }

    Test& operator=(const Test&) {
        cout << setw(20) << "copy assignment ";
        PrintAddress();
        return *this;
    }

    Test(Test&& other) {
        cout << setw(20) << "move constructor ";
        PrintAddress();
    }

    Test& operator=(Test&&) {
        cout << setw(20) << "move assignment ";
        PrintAddress();
        return *this;
    }

    virtual ~Test() {
        cout << setw(20) << "destructor ";
        PrintAddress();
    }

    void PrintAddress() {
        cout << "Test&: " << this << endl;
    }
};

Test regular_test (Test t) {
    cout << "regular_test" << endl;
    return t;
}

int main() {
    cout << "start" << endl;
    function<Test(Test)> lambda_test = [] (Test t) {
        cout << "lambda_test" << endl;
        return t;
    };
    Test t;
    lambda_test(t);
    //regular_test(t);
    cout << "done" << endl;
    return 0;
}
start
        constructor Test&: 0x7fffef6faf28
   copy constructor Test&: 0x7fffef6faf08
   move constructor Test&: 0x7fffef6fade8
lambda_test
   move constructor Test&: 0x7fffef6faf10
         destructor Test&: 0x7fffef6fade8
         destructor Test&: 0x7fffef6faf10
         destructor Test&: 0x7fffef6faf08
done
         destructor Test&: 0x7fffef6faf28
C++ Lambda 复制构造函数 move-constructor

评论

0赞 CGi03 9/3/2022
自动:function<Test(Test&)>

答:

1赞 apple apple 9/3/2022 #1

因为 std::function::operator() 是基于类的模板类型定义的。

R operator()( Args... args ) const; // Args are parameter of the *class*

所以会有 ,它会自己制作一个副本,然后转发到 (移动)std::function<Test(Test)>Test operator()(Test)lambda_test

评论

0赞 David Carpenter 9/4/2022
好的,但为什么要改变来解决问题呢?function<Test(Test)> lambda_testauto lambda_test
0赞 apple apple 9/4/2022
@DavidCarpenter,因为 auto 不会添加另一个包装器。(Lambda 甚至没有被复制)