Boost logo

Boost Users :

Subject: [Boost-users] [bind][function] Do copy constructors invoked inside boost::bind / boost::function get optimized out?
From: Steve Lorimer (steve.lorimer_at_[hidden])
Date: 2010-07-26 18:05:45


Hi

I'm using boost::bind to convert a function of the form:
T::fun(boost::intrusive_ptr<U>) into a form which can be stored by
boost::function.

Outputting calls to intrusive_ptr_add_ref and intrusive_ptr_release reveals
there are a massive number of copies of the intrusive_ptr. For a single call
of boost::bind on a

I'm wondering what kind of overhead this will add if I'm calling boost::bind
on boost::intrusive_ptr a LOT of times? Will the copies be optimized out?

There are 6 calls to intrusive_ptr_add_ref when calling boost::bind to bind
a member function pointer to an object which is wrapped up in an
intrusive_ptr
There are 5 calls to intrusive_ptr_add_ref when calling boost::bind to bind
an argument which is an intrusive_ptr
There are 12 calls to intrusive_ptr_add_ref when using boost::function to
store the result of boost::bind when called to bind a member function
pointer to an object which is wrapped up in an intrusive_ptr
There are 11 calls to intrusive_ptr_add_ref when using boost::function to
store the result of boost::bind when called to bind an argument which is an
intrusive_ptr

Example code and output showing the calls below:

#include <iostream>
#include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

struct ref_ctd
{
    int refs;
    ref_ctd() : refs(0) { }
};

template<typename T>
void intrusive_ptr_add_ref(T* p)
{
    cout << "++ setting p (" << p << ")'s refs to " << p->refs + 1 << endl;
    ++p->refs;
}

template<typename T>
void intrusive_ptr_release(T* p)
{
    cout << "-- setting p (" << p << ")'s refs to " << p->refs - 1 << endl;
    if (!--p->refs)
        delete p;
}

struct foo : public ref_ctd
{
    void func(char a) { cout << a << endl; }
};

void bar(boost::intrusive_ptr<foo> f)
{
    f->func('b');
}

int main()
{
    cout << "--------- creating intrusive ptr ----------" << endl;
    boost::intrusive_ptr<foo> f(new foo);
    cout << "--------- binding intrusive_ptr object ----------" << endl;
    boost::bind(&foo::func, f, 'a');
    cout << "--------- now storing result of bind ----------" << endl;
    boost::function<void()> func1 = boost::bind(&foo::func, f, 'a');
    cout << "--------- binding intrusive_ptr object ----------" << endl;
    boost::bind(bar, f);
    cout << "--------- now storing result of bind ----------" << endl;
    boost::function<void()> func2 = boost::bind(bar, f);
    return 0;
}

Here are the results:

--------- creating intrusive ptr ----------
++ setting p (0x33b18)'s refs to 1
--------- binding intrusive_ptr object ----------
++ setting p (0x33b18)'s refs to 2
++ setting p (0x33b18)'s refs to 3
++ setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
-- setting p (0x33b18)'s refs to 3
-- setting p (0x33b18)'s refs to 2
-- setting p (0x33b18)'s refs to 1
--------- now storing result of bind ----------
++ setting p (0x33b18)'s refs to 2
++ setting p (0x33b18)'s refs to 3
++ setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
-- setting p (0x33b18)'s refs to 3
++ setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
++ setting p (0x33b18)'s refs to 7
++ setting p (0x33b18)'s refs to 8
++ setting p (0x33b18)'s refs to 9
-- setting p (0x33b18)'s refs to 8
-- setting p (0x33b18)'s refs to 7
-- setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
-- setting p (0x33b18)'s refs to 3
-- setting p (0x33b18)'s refs to 2
--------- binding intrusive_ptr object ----------
++ setting p (0x33b18)'s refs to 3
++ setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
-- setting p (0x33b18)'s refs to 3
-- setting p (0x33b18)'s refs to 2
--------- now storing result of bind ----------
++ setting p (0x33b18)'s refs to 3
++ setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
++ setting p (0x33b18)'s refs to 5
++ setting p (0x33b18)'s refs to 6
++ setting p (0x33b18)'s refs to 7
++ setting p (0x33b18)'s refs to 8
++ setting p (0x33b18)'s refs to 9
++ setting p (0x33b18)'s refs to 10
-- setting p (0x33b18)'s refs to 9
-- setting p (0x33b18)'s refs to 8
-- setting p (0x33b18)'s refs to 7
-- setting p (0x33b18)'s refs to 6
-- setting p (0x33b18)'s refs to 5
-- setting p (0x33b18)'s refs to 4
-- setting p (0x33b18)'s refs to 3
-- setting p (0x33b18)'s refs to 2
-- setting p (0x33b18)'s refs to 1
-- setting p (0x33b18)'s refs to 0



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net