Ответ 1
std::bind()
принимает свои аргументы по значению. Это означает, что в первом случае вы передаете указатель по значению, в результате чего получается копия указателя. Во втором случае вы передаете объект типа foo
по значению, в результате чего получается копия объекта типа Foo
.
Как следствие, во втором случае вычисление выражения L()
вызывает функцию-член get()
для копии исходного объекта foo
, который может быть, а может и не быть тем, что вы хотите.
Этот пример иллюстрирует разницу (забудьте о нарушении правила трех/правила пяти, это только для иллюстрации):
#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
}
Если по какой-либо причине вы не хотите использовать форму указателя, вы можете использовать std::ref()
, чтобы предотвратить создание копии аргумента:
auto L = std::bind(&Foo::get, std::ref(foo), 3);