std::bind的奇怪行为

strange behavior of std::bind

本文关键字:bind std      更新时间:2023-10-16

我使用这个std::bind绑定类外的函数,并给出了一个奇怪的行为。

它在某种程度上控制了私有成员变量的值。

//MClass.h
typedef std::function<void(void)> Action;
class MClass {
public:
  Action OnLeftClick;
//some other functions here
private:
  int totalContents;
  VScrollbar* _vscrollbar;
};
//MClass.cpp

在这种实现中,它不会产生任何错误:

MClass::MClasss() {
  OnLefClick = std::bind(&VScrollbar::Scrolldown, this);
}
//but when I do this
//otherfile.h
MClass mclass;
void clickBar() {
  mclass.totalContents = 0;
}
void InitComponentns() {   
mclass.OnLeftClick = std::bind(clickBar, mclass);
}

并且每当我调用分配给CCD_ 2的函数即CCD_,CCD_ 4的值不改变为0(totalContents值由MClass的其它函数递增)。

我在这里做错什么了吗?

std::bind调用中的this参数实际上是函数的第一个参数。对于成员函数,它必须是该函数所属类的实例,因为所有成员函数都有一个隐藏的第一个参数,即this指针。

因此,要使代码工作,VScrollbar::Scrolldown的第一个参数必须是VScrollbar类的实例,而不是MClass中的this。像这样:

OnLefClick = std::bind(&VScrollbar::Scrolldown, _vscrollbar);

对于第二个std::bind调用,您应该只向它传递函数指针,因为它是一个不带参数(隐藏或不隐藏)的函数:

mclass.OnLeftClick = std::bind(clickBar);

不过,我对问题中的代码构建感到惊讶,因为totalContents成员变量是私有的,不能从clickBar函数访问。

首先,您不能将mclass绑定到clickBar,因为函数不带参数。您可以修改函数以引用MClass:

void clickBar(MClass& m) { m.totalContents = 42; }

其次,即使可以,bind也会复制mclass。您可以使用std::ref:传递std::reference_wrapper

#include <functional>
struct MClass { int totalContents = 0;};
void clickBar(MClass& m) { m.totalContents = 42; }
int main() {   
  MClass mclass;
  auto OnLeftClick = std::bind(clickBar, std::ref(mclass));
  OnLeftClick();
}