Reputation: 1138
I was hoping to understand what kind of internal copies of a function object does boost::bind do. Since constructors of these objects do not seem to be invoked, I presumed this is a kind of "very shallow copy", so I introduced dynamic memory allocations to produce some errors. However, runtime output of the code below seems to indicate three additional destructor calls for internal copies made by bind.
using namespace std;
using namespace boost;
class M{
int *somedata;
public:
M(){ somedata=new int[5]; cout<<"from cstr\n"; somedata[1]=0;}
~M(){cout<<"from dstr\n"; delete somedata;}
int operator()(int i){ cout<<++somedata[i]<<endl; return 0;}
};
int main()
{
M instM;
bind<int>(instM,1)();
//bind<int>(&M::operator(),&instM,1)(); //this works with no errors, of course
instM(1); //would not change the order of output
return 0;
}
The output ... presents some additional puzzles - eg. why first dstr event comes before call to operator()? Also notice the "2" before the last failed destructor call.
from cstr
from dstr
1
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug
2
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug
So the question is: can anyone explain briefly in what order, and what kind of copies does bind make?
... After some thought I realized bind is simply using the (here default) copy constructor. After supplying some custom version of this cstr (with memory allocation and as-deep-as-one-wishes version of the copy) the output gets clean (as it should), but the puzzle remains: there are three invocations of the copy constructor. So in this case boost::bind makes three copies of the function object. Why and in which order? (For nested boost::binds this can lead to quite explosive growth of the number of internal copies.)
Output with cp-cstr defined, and some "heritage markers" added ("P"=parent, each cp cstr adds "-C"):
from cstr P
from cp cstr P-C
from cp cstr P-C-C
from cp cstr P-C-C-C
from dstr P-C-C
P-C-C-C:1
from dstr P-C-C-C
from dstr P-C
P:1
from dstr P
Upvotes: 4
Views: 782
Reputation: 79185
See here:
By default, bind makes a copy of the provided function object. boost::ref and boost::cref can be used to make it store a reference to the function object, rather than a copy. This can be useful when the function object is noncopyable, expensive to copy, or contains state; of course, in this case the programmer is expected to ensure that the function object is not destroyed while it's still being used.
Upvotes: 2