使用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节),但它是我不太清楚的地方之一。
只有一个是正确的,还是两个都正确?
答案 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
的成员函数的指针时,t1
是T
类型的对象或对T
的引用类型为T
的对象或对从((*t1).*f)(t2, ..., tN)
派生的类型的对象的引用;-
f
当T
是指向类t1
的成员函数的指针时,t1.*f
不是上一项中描述的类型之一;-
N == 1
当f
和T
是指向类t1
的成员数据的指针时,T
是T
类型的对象}或对类型为T
的对象的引用或对从(*t1).*f
派生的类型的对象的引用;-
N == 1
当f
和T
是指向类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的成员数据所做的更改。