为什么在 lambda 中移动时不调用移动构造函数?

Why is the move constructor not called when moving in a lambda?

我正在尝试编译以下代码:

#include <utility>

struct C2 {
        C2() = default;
        C2(C2 const&) = delete;
        C2(C2&&) = default;
};

int main() {
        C2 p2;
        ([p2_1{ std::move(p2) }]() {
                auto p2_2 = std::move(p2_1); // <---
        })();
        return 0;
}

但是,这不会编译并给出错误,即对 p2_2 的赋值正在调用已删除的函数,即复制构造函数。请注意,移动到 p2_1 没问题。为什么这不使用移动构造函数?

这里的问题是 lambda 表示的匿名 class 类型的 operator() 默认是 const。这意味着您不能从 p2_1 移动,因为 lambda 的 this 在函数中是 const& 。您需要做的是使用 mutable 关键字,例如

int main() {
        C2 p2;
        ([p2_1{ std::move(p2) }]() mutable {
                auto p2_2 = std::move(p2_1); // <---
        })();
        return 0;
}

这使得函数成为非 const,这反过来意味着您可以改变其成员。这允许您移动 p2_1 而不是试图复制它。