64

用于std::bind绑定成员函数时,第一个参数是对象this指针。但是,它可以将对象作为指针而不是作为指针传递。

例如,请参见以下程序:

#include <iostream>
#include <functional>

struct foo
{
    void bar(int v) { std::cout << "foo::bar - " << v << '\n'; }
};

int main()
{
    foo my_foo;

    auto f1 = std::bind(&foo::bar, my_foo, 1);
    auto f2 = std::bind(&foo::bar, &my_foo, 2);

    f1();
    f2();
}

clang 和 GCC 都毫无怨言地编译了这个,结果对两个绑定都有效:

富::酒吧 - 1
富::酒吧 - 2

我一直在尝试围绕规范(第 20.8.9 节)展开思考,但这是我不清楚的地方之一。

应该只有一个是正确的,还是两个都正确?

4

3 回答 3

51

两者都是正确的。20.8.9.1.2 转发到 20.8.2 以描述您调用的要求和效果bind。20.8.2 是:

20.8.2 要求 [func.require]

1按如下方式定义INVOKE :(f, t1, t2, ..., tN)

(t1.*f)(t2, ..., tN)whenf是指向类的成员函数的指针,T并且t1是类型对象T或对类型对象的T引用或对派生于的类型对象的引用T

((*t1).*f)(t2, ..., tN)whenf是指向类的成员函数的指针,T并且t1不是上一项中描述的类型之一;

t1.*fN == 1andf是指向类的成员数据的指针T并且t1是类型对象T或对类型对象的T引用或对派生于的类型对象的引用时T

(*t1).*fwhenN == 1f是指向类的成员数据的指针,T并且t1不是上一项中描述的类型之一;

f(t1, t2, ..., tN)在所有其他情况下。

前两个选项允许引用和指针。

这里要注意的重要一点是,措辞并不局限于简单的指针。您可以使用一个或其他一些智能指针来使您的实例在绑定时保持活动状态,并且无论它是什么(当然,假设它是可能的),std::shared_ptr它仍然可以与取消引用std::bind一样工作。t1

于 2013-03-07T05:56:05.140 回答
3

添加到正确答案(两种形式都允许)。

我认为这两个绑定选项类似于函数参数声明,可能是“按值传递”或“按引用传递”。

f1(又名my_foo“按值”传递)的情况下,结果不会“看到”my_foo对绑定点之后所做的任何更改。这可能不是所希望的,尤其是在my_foo进化的情况下。“按值”绑定具有对复制构造函数的(多次)调用的额外“成本”。

于 2016-07-18T08:49:14.903 回答
-1

它们是有区别的。正如 rytis 提出的,按值传递不会看到对 my_foo 所做的更改。例如,如果 my_foo 是一个类,按值传递不会看到对 my_foo 的成员数据所做的更改。

于 2016-10-16T22:43:18.963 回答