传递和存储lambda函数作为回调

时间:2013-03-27 05:59:55

标签: c++ c++11 callback lambda

我想知道这是否是一种可接受的写回调的方法:

存储回调:

struct EventHolder {
    std::function<void()> Callback;
    EventTypes::EventType Type;
};
std::vector<Events::EventHolder> EventCallbacks;

方法定义:

void On(EventType OnEventType,std::function<void()>&& Callback)
{
    Events::EventHolder NewEvent;
    NewEvent.Callback=std::move(Callback);
    NewEvent.Type=OnEventType;
    EventCallbacks.push_back(std::move(NewEvent));
}

绑定事件:

Button->On(EventType::Click,[]{
    // ... callback body
});

我最大的问题是关于通过值传递回调。这是一种有效的方法吗?

3 个答案:

答案 0 :(得分:12)

这是存储事件处理程序的完美有效方法。

但是,我想指出一些关于添加回调函数签名的细节。你担心通过值和引用传递它。在您的示例中,您目前拥有:

void On(EventType OnEventType,std::function<void()>&& Callback)

这很好,只要你只将它绑定到右值。但是,除非您有特殊原因要禁止它,否则我建议您始终使用一个方法接受按值或左值引用的参数,并在必要时添加右值参考版本作为补充。

没有采用左值引用的方法意味着您的代码目前无法编译,因为:

std::function<void()> func([](){/*something clever*/});
// Do something necessary with func, perhaps logging or debug prints.
Button->On(EventType::Click, func);

为简单起见,无论何时选择如何传递值,您都可以简单地遵循以下指南:

  • 如果您需要副本或打算修改发送的值,而不想更改传递的实际对象:按值传递。
  • 如果您打算修改发送的值,并希望这些更改影响传递的实际对象:按引用传递。
  • 如果您不想更改传递的对象,但认为避免复制是有益的:传递const引用。
  • 如果按值,引用或const引用获取参数,并且相信使用输入参数是临时的知识可以实现有价值的优化:也允许通过右值引用。

答案 1 :(得分:1)

是。函数是原始函数指针或轻量级类,它们的复制构造函数没有副作用,因此它们的副本必须充当原始对象,因此这种方法完全没问题。但是为什么你按值传递对象然后将其移动到原始容器,你可以传递引用,然后将它复制到你的容器,并有一个接受r值引用的重载函数(不应该那么重要)。

答案 2 :(得分:0)

我有几乎相同的问题。 我想知道有多少台监视器以及它们在哪里。

至少我放弃并写了一个简短的结构。 不好,但是我只想要信息。

即使我尝试过Lambda,也没有机会定义Lambda ... 不是固定的地址,其次不能构造为回呼...

#include <WinUser.h>
#include <vector>
using namespace std;

struct _sMonitors{
        struct DispInfo {
            HMONITOR    hMon;
    //      HDC         dcMon;      // Everytime NULL (What ever!)
            RECT        pRcMon;
        };
        list< DispInfo> List;
        _sMonitors() {
            EnumDisplayMonitors(0, 0, Func, (LPARAM)this);
        }
        BOOL static CALLBACK Func(HMONITOR hMon, HDC dcMon, LPRECT pRcMon, LPARAM lParam){
            auto& Struct = *((_sMonitors*)lParam);
            Struct.List.push_back({ hMon,*pRcMon });
            return 1; 
        }
};
_sMonitors Monitors;

正如我用我的语言所说! Mann ging mir das auf den Sack ...