【问题标题】:Cannot pass std::unique_ptr in std::function<>无法在 std::function<> 中传递 std::unique_ptr
【发布时间】:2021-06-29 09:51:36
【问题描述】:
#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;
    });
}

以下代码编译时出错

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

  1. 为什么会这样?
  2. 有没有办法在 std::function 中传递 std::unique_ptr 而不通过引用传递它?

【问题讨论】:

  • 你不能复制一个unique_ptr它的复制构造函数被删除了。
  • std::function 复制。
  • 如果std::function&lt;void()&gt; 是必须的,那么您可能需要传递指针[h = handle.get()]()
  • @Jarod42,当 std::function 复制了 unique_ptr?如果替换 void foo(std::function&& f) 问题也会重现
  • @PeterDevenyi,这是最小的可重现示例,在实际情况下,我应该将 unique_ptr 的生命周期传递给 lambda

标签: c++ function lambda unique-ptr


【解决方案1】:

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

        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));

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

【讨论】:

  • 谢谢,对我有帮助。这个解决方案甚至可以 void foo() take f by copy
  • 您不必更改foo,但是您需要注意它如何使用f,因为在foo 结束引用后f 的副本内将悬空
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多