|
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<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
specialization:
namespace std
{
template<class X>
class auto_ptr<X[]>
{
public:
typedef X element_type;
// lib.auto.ptr.cons 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_;}
// lib.auto.ptr.members 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);}
// lib.auto.ptr.conv 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;}
private:
X* ptr_;
};
}
Now the example code does compile and has the expected semantics:
auto_ptr<char []> ptr(new char[100]);
Notes:
1. Conversions from derived to base pointers are not supported in
this specialization since that would result in undefined behavior
(5.3.5/3).
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?
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk