24

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

存储回调:

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

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

4

3 回答 3

16

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

但是,我想指出一些有关添加回调的函数签名的细节。您担心按值传递它而不是按引用传递。在您的示例中,您当前拥有:

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 引用获取参数,并相信可以使用输入参数是临时的知识来实现​​有价值的优化:也允许通过右值引用传递。
于 2013-03-27T06:47:38.050 回答
1

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

于 2013-03-27T06:06:31.003 回答
0

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

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

即使是我尝试过的 Lambda,也没有机会定义 Lambda ...不是固定的 Addr 和 second 不能构造为 CALLBACK ...

#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...

于 2020-09-29T15:36:41.983 回答