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:
auto L = std::bind(&Foo::get, foo, 3);
Why?
std::bind. The function template bind generates a forwarding call wrapper for f . Calling this wrapper is equivalent to invoking f with some of its arguments bound to args .
Bind function with the help of placeholders helps to manipulate the position and number of values to be used by the function and modifies the function according to the desired output. What are placeholders? Placeholders are namespaces that direct the position of a value in a function.
The std::bind will be copied into heap allocated by the std::function and the std::function will be copied into heap allocated by the std::vector .
std::bind return type The return type of std::bind holds a member object of type std::decay<F>::type constructed from std::forward<F>(f), and one object per each of args... , of type std::decay<Arg_i>::type, similarly constructed from std::forward<Arg_i>(arg_i).
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
.
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.
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
#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
}
Live example.
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:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With