Reputation: 33
#include <functional>
#include <iostream>
using namespace std;
class test {
public:
test(){ p = new int[10];}
void print_info(double a)
{
cerr << a << endl;
}
~test(){
cerr << __LINE__ << endl;
delete []p;
}
private:
int *p;
};
int main()
{
test t;
std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);
//std::function<void(void)> f = std::bind(&test::print_info, std::cref(t), 2.0);
return 0;
}
It will crash, since test::~test()
is called twice. But, if I replace t
with std::cref(t)
(or std::ref(t), &t
), ~test()
will be called only once when exiting main().
I didn't figure out the reason. I'm on Ubuntu 12.04 64bit, using gcc 4.6.3.
Upvotes: 3
Views: 4907
Reputation: 208323
std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);
It will crash, since test::~test() is called twice. But, if I replace t with std::cref(t) (or std::ref(t), &t), ~test() will be called only once when exiting main().
I didn't figure out the reason. I'm on Ubuntu 12.04 64bit, using gcc 4.6.3.
The reason is actually quite simple, the std::bind
function creates a functor object that holds a copy of the arguments. In your program there is a bug and copying objects of the type end up with two objects having pointers to the same memory and both calling delete[]
in their destructors.
When you bind &t
the address of the object (pointer) gets copied. There are no two separate objects, just one object and a pointer. Similarly the utilities std::ref
and std::cref
are reference wrappers, that is objects that wrap a different object and provide reference-like semantics. No matter how many times std::ref
is copied, all of the copies behave as references to the same object. The object itself is never copied.
Upvotes: 0
Reputation: 254431
You're binding a copy of the object t
. Since your class tries to manage dynamic memory, but doesn't follow the Rule of Three, it has invalid copy semantics - both copies will try to delete the same dynamic array on destruction.
If you used a class like std::vector
, with valid copy semantics, to manage the dynamic array, then all would be fine.
Upvotes: 9
Reputation: 55887
Since you are binding a copy of object t
, not t
itself, that will be destructed when returning from bind
object will be destructed and since you don't overload copy c-tor, default copy c-tor will make shallow copy and your p
will be deleted twice. For binding t
itself you should use std::ref
.
Upvotes: 4