首页 > 解决方案 > 在不复制的情况下返回 std::function

问题描述

从函数调用返回 a 时std::function,返回的函数是函数定义的副本,还是对函数的引用?

背景:我想在我的应用程序的某些或多或少对性能敏感的部分避免瓶颈。因此,我想避免在不需要的地方进行分配和复制。

示例代码:

typedef std::function<std::unique_ptr<ControllerResponse>(
    const std::vector<std::string> &pathComponents,
    const std::string &data,
    const std::unordered_map<std::string, std::string> &params)
> ControllerMethod;

ControllerMethod RouteIndex::findRoute(
    const std::vector<std::string> &pathComponents,
    const std::string &method,
    std::map<std::string, std::string> &requestParams) {
   // ... snip
   // suppose globalMap is a class member
   return globalMap.InstanceOfControllerMethod;
}

findRoute()返回一个副本还是std::function本身只是一个参考?

标签: c++c++14c++17

解决方案


C++ 标准对std::function复制构造函数有这样的说法:

function(const function& f);

f抛出:如果' 的目标是一个特化的reference_wrapper或函数指针,则不应抛出异常。否则,可能会抛出 bad_alloc或由存储的可调用对象的复制构造函数抛出的任何异常。[注意:鼓励实现避免为小的可调用对象使用动态分配的内存,例如,其中f的目标是一个只包含一个指针或对一个对象的引用和一个成员函数指针的对象。——尾注]

请务必阅读说明。如果你保持你的回调很小,你应该能够在std::function不进行动态分配的情况下进行复制。

因此,在您的示例中,如果InstanceOfControllerMethod是函数指针,则返回副本不应分配内存。但是如果你想把一个成员函数指针放进去,你应该使用 lambda,因为 C++ 中的成员函数指针在很多方面都被破坏了,并且可能太大而无法放入std::function

std::function<void()> get_member_function(A *p)
{
    return [p]() { p->function(); };
}

由于此类 lambda 仅包含指针p,因此可以保证适合std::function实例,这与成员函数指针不同,它可以采用 2 个或更多指针。


推荐阅读