Boost logo

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