|
Boost : |
From: Bill Wade (bill.wade_at_[hidden])
Date: 2000-08-22 10:35:17
> -----Original Message-----
> From: Milutin Jovanovic [mailto:miki_at_[hidden]]
> From: "David Abrahams" <abrahams_at_[hidden]>
> > 1. noncopyable can be used when no sensible copy semantics
> exist. There is
> > simply no analogue for dynamic construction. If it makes sense to write
> > X x;
> > then it also makes sense to say
> > std::auto_ptr<X> x(new X);
>
> Until recently I did not see much use for it, but we have a
> concrete example
> in our thread conversations. The mutex_lock class that locks a mutex only
> within a scope
I would say that the mutex_lock class "locks a mutex only during an object's
lifetime." Many objects' lifetimes correspond to a scope, and that is often
a good way to use mutex_lock. I don't see any particular reason to make it
the only way to use a mutex_lock (and David has already replied with a good
counter-example).
However I do believe that there are some borderline "real" cases where it is
convenient to ensure that objects are not allocated on the heap:
1) I may want to enforce strict LIFO lifetimes for my class. If every
instance of my class "registers" itself upon construction and "deregisters"
itself upon destruction, the registration/deregistration code can be
significantly faster if a precondition is stack-style lifetimes. Causing a
compile time error if someone tries to put my object on the heap may prevent
some runtime errors. Note the assert() in the destructor below.
// Support debug traces. Not MT safe.
class stack_trace: public not_on_heap
{
// The current stack is represented as a singly linked list
// of existing objects. This code is roughly twice as fast
// as the doubly linked list that would be required to allow
// objects to be destroyed in non-stack order.
static stack_trace const* stack;
stack_trace const*const next;
char const*const context_name; // Not owned.
public:
// Name should be a literal, or at least outlive this object.
// This object does a shallow copy of the pointer.
stack_trace(const char* name): context_name(name), next(stack)
{
stack = this;
}
~stack_trace()
{
assert(stack == this);
stack = next;
}
static void PrintStack(ostream& os)
{
for(stack_trace* current = stack; stack_trace;
current = current->next)
os << current->context_name << '\n';
}
};
2) I may want to take advantage of the how a particular implementation
defines what the standard calls undefined behavior while accessing a const
or volatile object through a non-cv reference. Note that for all practical
purposes there are no cv objects on the heap.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk