无法在 std::function<> 中传递 std::unique_ptr

mag*_*cDM 4 c++ lambda function unique-ptr

#include <functional>
#include <memory>
#include <string>
#include <iostream>

void foo(std::function<void()> f)
{
    f();
}

int main()
{
    std::unique_ptr<int> handle = std::make_unique<int>(5);
    foo(
        [h = std::move(handle)]() mutable
    {
        std::cout << *h << std::endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

以下代码不会编译出错

C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\include\functional(914,58): 错误 C2280: 'main::<lambda_1aa523ba59bbecea5306bc1fd>1781bc1fd178c1fd178c1fd178c1fd1781bc1fd1781bc1fd1781bc1fd1781b >(const main::<lambda_1aa523ba59bbecea5306bc1fd178120f> &)':试图引用已删除的函数

  1. 为什么会发生?
  2. 有没有办法在 std::function<void()> 中传递 std::unique_ptr 而不通过引用传递它?

Мор*_*лав 9

std::function要求函数对象是可复制构造的,因此您不能指望将 lamdba 移动到它。在初始化时,它尝试复制 lambda 等std::unique_ptr,它是此 lambda 的成员,但预计会失败。您可以做的是将您的 lambda 存储在一个变量中,并将其传递给接受这样const std::function&使用的函数std::ref

        void foo(const std::function<void()>& f); // function declaration
        auto a = [h = std::move(handle)]() mutable
        {
            std::cout << *h << std::endl;
        };
        foo(std::ref(a));
Run Code Online (Sandbox Code Playgroud)

这是一个具有更详细答案的相关问题:How to create an std::function from a move-capturing lambda expression?

  • 您不必更改“foo”,但是您确实需要注意它如何使用“f”,因为“foo”结束后“f”副本内的引用将悬空 (3认同)