I have this code:
我有这段代码:
#include <iostream>
#include <functional>
struct Foo
{
int get(int n) { return 5+n; }
};
int main()
{
Foo foo;
auto L = std::bind(&Foo::get, &foo, 3);
std::cout << L() << std::endl;
return 0;
}
Seems that this:
似乎这个:
auto L = std::bind(&Foo::get, &foo, 3);
is equivalento to:
是equivalento:
auto L = std::bind(&Foo::get, foo, 3);
Why?
为什么?
2 个解决方案
#1
14
std::bind()
accepts its arguments by value. This means that in the first case you are passing a pointer by value, resulting in the copy of a pointer. In the second case, you are passing an object of type foo
by value, resulting in a copy of an object of type Foo
.
bind()按值接受其参数。这意味着在第一种情况下,您正在按值传递一个指针,从而导致一个指针的拷贝。在第二种情况下,您正在传递一个按值为foo类型的对象,结果是一个foo类型的对象的副本。
As a consequence, in the second case the evaluation of the expression L()
causes the member function get()
to be invoked on a copy of the original object foo
, which may or may not be what you want.
因此,在第二种情况下,表达式L()的求值会导致成员函数get()在原始对象foo的副本上被调用,这可能是您想要的,也可能不是。
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
这个例子说明了不同之处(忘记3 / 5规则的违反,这只是为了说明):
#include <iostream>
#include <functional>
struct Foo
{
int _x;
Foo(int x) : _x(x) { }
Foo(Foo const& f) : _x(f._x)
{
std::cout << "Foo(Foo const&)" << std::endl;
}
int get(int n) { return _x + n; }
};
int main()
{
Foo foo1(42);
std::cout << "=== FIRST CALL ===" << std::endl;
auto L1 = std::bind(&Foo::get, foo1, 3);
foo1._x = 1729;
std::cout << L1() << std::endl; // Prints 45
Foo foo2(42);
std::cout << "=== SECOND CALL ===" << std::endl;
auto L2 = std::bind(&Foo::get, &foo2, 3);
foo2._x = 1729;
std::cout << L2() << std::endl; // Prints 1732
}
生活的例子。
If, for any reason, you don't want to use the pointer form, you can use std::ref()
to prevent a copy of the argument from being created:
如果由于任何原因,您不想使用指针形式,您可以使用std:::ref()来防止创建参数的副本:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
#2
3
They are not the same. The generic function binder std::bind
copies it's arguments. In the case of std::bind(&Foo::get,&foo,3)
, the pointer is copied, but when you call the bound object it still applies to the original foo
object. In std::bind(&Foo::get,foo,3)
the object foo
is copied, and the later call applies to the bound copy, not to the original object.
他们不一样。通用函数binder std::bind拷贝它的参数。在std::bind(&Foo: get, &Foo,3)的情况下,指针被复制,但是当您调用绑定对象时,它仍然适用于原始的foo对象。在std::bind(&Foo: get,foo,3),对象foo被复制,后面的调用应用于绑定复制,而不是原始对象。
You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.
您可以通过使用访问对象内部状态的成员函数来测试它,在两种方法中绑定对象,更改原始对象,并查看结果如何不同。
#1
14
std::bind()
accepts its arguments by value. This means that in the first case you are passing a pointer by value, resulting in the copy of a pointer. In the second case, you are passing an object of type foo
by value, resulting in a copy of an object of type Foo
.
bind()按值接受其参数。这意味着在第一种情况下,您正在按值传递一个指针,从而导致一个指针的拷贝。在第二种情况下,您正在传递一个按值为foo类型的对象,结果是一个foo类型的对象的副本。
As a consequence, in the second case the evaluation of the expression L()
causes the member function get()
to be invoked on a copy of the original object foo
, which may or may not be what you want.
因此,在第二种情况下,表达式L()的求值会导致成员函数get()在原始对象foo的副本上被调用,这可能是您想要的,也可能不是。
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
这个例子说明了不同之处(忘记3 / 5规则的违反,这只是为了说明):
#include <iostream>
#include <functional>
struct Foo
{
int _x;
Foo(int x) : _x(x) { }
Foo(Foo const& f) : _x(f._x)
{
std::cout << "Foo(Foo const&)" << std::endl;
}
int get(int n) { return _x + n; }
};
int main()
{
Foo foo1(42);
std::cout << "=== FIRST CALL ===" << std::endl;
auto L1 = std::bind(&Foo::get, foo1, 3);
foo1._x = 1729;
std::cout << L1() << std::endl; // Prints 45
Foo foo2(42);
std::cout << "=== SECOND CALL ===" << std::endl;
auto L2 = std::bind(&Foo::get, &foo2, 3);
foo2._x = 1729;
std::cout << L2() << std::endl; // Prints 1732
}
生活的例子。
If, for any reason, you don't want to use the pointer form, you can use std::ref()
to prevent a copy of the argument from being created:
如果由于任何原因,您不想使用指针形式,您可以使用std:::ref()来防止创建参数的副本:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
#2
3
They are not the same. The generic function binder std::bind
copies it's arguments. In the case of std::bind(&Foo::get,&foo,3)
, the pointer is copied, but when you call the bound object it still applies to the original foo
object. In std::bind(&Foo::get,foo,3)
the object foo
is copied, and the later call applies to the bound copy, not to the original object.
他们不一样。通用函数binder std::bind拷贝它的参数。在std::bind(&Foo: get, &Foo,3)的情况下,指针被复制,但是当您调用绑定对象时,它仍然适用于原始的foo对象。在std::bind(&Foo: get,foo,3),对象foo被复制,后面的调用应用于绑定复制,而不是原始对象。
You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.
您可以通过使用访问对象内部状态的成员函数来测试它,在两种方法中绑定对象,更改原始对象,并查看结果如何不同。