Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2000-11-24 06:37:26


From: "Kevlin Henney" <kevlin_at_[hidden]>

> In message <200011230812.AAA19587_at_[hidden]>, Jesse Jones
> <jesjones_at_[hidden]> writes
> >
> >Sure, but if 99% of the time I'm wrapping function_ptr up in a shared_ptr
> >I'd begin to wonder why I couldn't just copy the damned callback object.

Well that's the point. You can copy the damned callback. Just don't do it in
an inner loop (and I know that you don't.)

> I've not found the need (where "want" and "need" are not the same idea
> ;->) to use anything but cloning, so I would be suspicious of figures
> like 99%... or indeed 9.9%.

This mirrors my experience. I always wait for the profiler to tell me what
to optimize and a copy constructor for a "cloning" object has never been a
performance hit.

Taking a bit less pragmatic view on that, I see three situations where the
need for reference counting would arise:

1. Extensive std::swap'ping (iter_swap'ping) - like in std::sort;
2. Function objects with state passed to standard algorithms;
3. std::vector reallocation.

My opinion is that all three are design flaws in the standard library.

1. Inability to supply std::swap for a template, or bad iter_swap that
doesn't use the user-provided std::swap.

2. A less clear issue, but the two sides are "design flaw" or "algorithms
aren't supposed to handle state in function objects anyway."

3. This is the most interesting. std::vector uses the primitive

// pre: p points to uninitialized memory, q points to an object of type T
// post: p points to an object of type T that is equivalent to *q

void copy(T * p, T * q)
{
    new(p) T(*q);
}

to relocate the elements. I think, however, that the primitive requirements
can be modified somewhat:

// pre: p points to uninitialized memory, q points to an object of type T
// post: p points to an object of type T that is equivalent to *q before the
call,
// q points to uninitialized memory
//
// exceptions: none
//

This is the equivalent of the "fast, non-throwing std::swap" except that the
first argument is uninitialized memory.

The idea would be that this primitive (std::move?) would be exposed, like
std::swap, for the class author to override.

--
Peter Dimov
Multi Media Ltd.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk