使用std :: bind和成员函数,对这个参数使用对象指针与否?

时间:2013-03-07 05:46:57

标签: c++ c++11 language-lawyer

使用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都没有投诉地编译它,结果适用于两种绑定:

foo::bar - 1
foo::bar - 2

我一直试图围绕规范(第20.8.9节),但它是我不太清楚的地方之一。

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

3 个答案:

答案 0 :(得分:49)

两者都是正确的。 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)f是指向类T的成员函数的指针时,t1T类型的对象或对T的引用类型为T的对象或对从((*t1).*f)(t2, ..., tN)派生的类型的对象的引用;

     

- fT是指向类t1的成员函数的指针时,t1.*f不是上一项中描述的类型之一;

     

- N == 1fT是指向类t1的成员数据的指针时,TT类型的对象}或对类型为T的对象的引用或对从(*t1).*f派生的类型的对象的引用;

     

- N == 1fT是指向类t1的成员数据的指针时,f(t1, t2, ..., tN)不是其中一种类型上一项;

     

- 在所有其他情况下std::shared_ptr

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

这里要注意的重要一点是,措辞限制你使用普通指针。您可以使用std::bind或其他一些智能指针来保持您的实例在绑定时保持活动状态,它仍然可以与t1一起使用,因为{{1}}被取消引用,无论它是什么(给定,当然,这是可能的。)

答案 1 :(得分:2)

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

我认为两个绑定选项类似于函数参数声明,它可以“通过值传递”或“通过引用传递”。

对于f1(又称my_foo“按值”),结果不会“看到”my_foo对绑定点所做的任何更改。如果my_foo发展,可能不需要这样做。 “按值”绑定具有对复制构造函数的(几次)调用的额外“成本”。

答案 2 :(得分:-1)

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