Why is "boost::function = boost::bind(...)" creating 13 temporaries?
Asked Answered
P

1

12

I have some pretty basic test code. I have a class that just logs all operations on it. I bound it to a boost::function object like this:

    void Function(const Foo&)
    {
        printf("Function invoked\n");
    }

    // ...

    boost::function<void(void)> func;
    {
        Foo f;
        printf("\nConstructing function\n");
        func = boost::bind(&Function, f);
        printf("Construction complete\n\n");
    }

I expect that the function object contains a copy of f. So creating at least one copy is mandatory. However, I find that I get 13 temporaries. Output is:

Constructing function
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::~Foo
Foo::Foo(const Foo&)
Foo::~Foo
Foo::~Foo
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::~Foo
Foo::~Foo
Foo::~Foo
Foo::~Foo
Foo::~Foo
Foo::Foo(const Foo&)
Foo::~Foo
Foo::Foo(const Foo&)
Foo::~Foo
Foo::~Foo
Foo::~Foo
Foo::~Foo
Construction complete

I can't use ref or cref because I do need it to make a copy of the object. Am I doing something horribly wrong? Or do I need to use a wrapper (like boost::shared_ptr) to avoid an absurd number of copies?

Full code and problem demonstration can be found on Codepad.

Pieria answered 31/1, 2013 at 3:11 Comment(8)
I'd be interested to see what std::bind does.Karikaria
Is this in debug or release?Slat
@NicolBolas Just compiling with g++, no special flags or options except -O2. Tried with and without c++11, no difference.Pieria
@chris: With std::function and std::bind, only two temporaries are created.Pieria
@DavidSchwartz Same with VC2012.Velum
I suspect boost::bind has not been upgraded for C++11.Ahouh
in my case boost::bind makes 14 copies and boost::function + std::bind makes 10 (gcc 4.7.2 -std=c++11 -O2). So it has to do with boost::function and boost::bind, not just boost::bindEquator
I just had the same case and I was shocked #20495016 . Have you tried using std::function? The performance is faaaar better (at least the copies are a lot fewer). +1 from me.Rosemaryrosemond
F
3

If you remove the "func = " assignment part the number of copies are lowered to 4 which is quite better than 13.

template <class F>
void callF(F fun)
{
}
callF(boost::bind(&func, fl));

So the solution is simple - don't use boost::function

Fadeless answered 31/1, 2013 at 8:28 Comment(4)
boost::thread(boost::bind(&Function, q)); gives me 7 temporaries.Pieria
i.post(boost::bind(&Function, q)); gives 6 temporaries.Pieria
hum, yes, in such case I think you were right to consider a shared_ptr if the object you are posting is not small enough to be faster passed by value or if you do not need too many of them. Test performance.Fadeless
I think you are right, the solution is to avoid boost::function if it all possible. If you can't, understand the costs. (Or go to c++11x)Pieria

© 2022 - 2024 — McMap. All rights reserved.