Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2001-01-04 14:35:46

The age old problem of smart pointers not working with pointers to
arrays has resulted in a lot of different solutions. A recent
posting to comp.lang.c++ sounds interesting and I thought some folks
on here might like to comment and maybe consider this technique for
some of the Boost smart pointers.

Original message from Howard Hinnant:

In article <ErM46.13826$534.6573_at_[hidden]>, "Luca"
<luca_at_[hidden]> wrote:
| Can auto_ptr handle raw arrays properly?
| auto_ptr<char []> ptr(new char[100]);
| Will the array be properly deleted when ptr goes out of scope?
Interesting syntax suggestion.
As others have stated, no this won't work. But I wanted to explore
your syntax suggestion a little...
auto_ptr<char []> ptr(new char[100]);
On my system this results in a compile-time error:
Error : function call 'auto_ptr(char *)' does not match
'std::auto_ptr<char[]>::auto_ptr(char (*)[])'
&)' 'std::auto_ptr<char[]>::auto_ptr<...>(std::auto_ptr<T1_0>
&)' 'std::auto_ptr<char[]>::auto_ptr(std::auto_ptr_ref<char[]>)'
HelloWorld2.cpp line 39 std::auto_ptr<char []> ptr(new char[100]);
This means to me that we could (non-portably for the moment)
specialize auto_ptr on X[] and give it the desired semantics without
worrying about changing the behavior of existing working code.
Here is an example specialization of auto_ptr on X[]. Note that it
is not portable because it depends upon implementation details of
auto_ptr_ref. Nevertheless, I believe that the idea should easily
port to any
environment with an existing std::auto_ptr and which supports partial
namespace std
template<class X>
class auto_ptr<X[]>
  typedef X element_type;
  // construct/copy/destroy:
  explicit auto_ptr(X* p = 0) throw() : ptr_(p) {}
  auto_ptr(auto_ptr& a) throw() : ptr_(a.release()) {}
  auto_ptr& operator=(auto_ptr& a) throw()
      {reset(a.release()); return *this;}
  ~auto_ptr() throw() {delete [] ptr_;}
  // members:
  X& operator*() const throw() {return *ptr_;}
  X* operator->() const throw() {return ptr_;}
  X* get() const throw() {return ptr_;}
  X* release() throw()
      {X* tmp = ptr_; ptr_ = 0; return tmp;}
  void reset(X* p = 0) throw()
      {if (ptr_ != p) {delete [] ptr_; ptr_ = p;}}
  X& operator[](size_t n) {return *(get() + n);}
  const X& operator[](size_t n) const {return *(get() + n);}
  // conversions:
  auto_ptr(auto_ptr_ref<X> r) throw() : ptr_(r.ptr_) {}
  auto_ptr& operator=(auto_ptr_ref<X> r) throw()
      {reset(r.ptr_); return *this;}
  operator auto_ptr_ref<X>() throw()
      {auto_ptr_ref<X> r; r.ptr_ = release(); return r;}
  X* ptr_;
Now the example code does compile and has the expected semantics:
auto_ptr<char []> ptr(new char[100]);
1. Conversions from derived to base pointers are not supported in
this specialization since that would result in undefined behavior
2. The specialization sports operator[] as a convenience.
    ptr[0] = ...;
    ptr[1] = ...;
    But attempts to use operator[] with non-array types (the original
auto_ptr) will compile-time.
I'm thinking along the lines of this being part of the next C++
standard. But it needs lots more field testing and thought than I can
give it alone.
This could have code size and/or speed advantages over the usual
suggestion to "use vector instead".
Thoughts? Comments? Opinions?

Boost list run by bdawes at, gregod at, cpdaniel at, john at