Hi all,
Most smart pointers remove the need to call delete. What I want is a
pointer that turns delete into a no-op for "unauthorized" clients.
The reason is that I'm generating code from pre-existing legacy code that
assumes the caller deletes the pointer. However, I want to reduce memory
copies for the case where there are multiple clients fetching a pointer to
the same memory.
Admittedly, this is a rare scenario, but I thought I'd share it with you
all for posterity and any feedback you can give me. (It seems like a bit
of a hack, especially if you notice that operator<< doesn't actually print
out the pointer.)
David
First, here's a toy program demonstrating the situation in the original code:
--------------%<---------------
#include <iostream>
using namespace std;
// Old code returned a copy for clients to delete
int* My_Library_To_Optimize()
{
static int *some_private_data = new int(10);
// Create a new copy for every caller, which is slow
return new int(*some_private_data);
}
int main()
{
int *p1 = My_Library_To_Optimize();
// This is the client code generated from legacy code. The client code
// can either delete the pointer, or pass it off to someone else to be
// deleted.
{
cout << *p1 << endl;
delete p1;
}
int *p2 = My_Library_To_Optimize();
// More client code
{
cout << *p2 << endl;
delete p2;
}
return 0;
}
--------------%<---------------
Here's the new code:
--------------%<---------------
#include <iostream>
#include "tough_ptr"
using namespace std;
// New code will return an indestructible pointer
tough_ptr<int>* My_Library_To_Optimize()
{
static int *some_private_data = new int(10);
// Copies of tough_ptr are cheaper
return new tough_ptr<int>(some_private_data);
}
int main()
{
tough_ptr<int> *p1 = My_Library_To_Optimize();
// Client code is unchanged! Delete does nothing!
{
cout << *p1 << endl;
delete p1;
}
tough_ptr<int> *p2 = My_Library_To_Optimize();
// Client code is unchanged! Delete does nothing!
{
cout << *p2 << endl;
delete p2;
}
return 0;
}
--------------%<---------------
Here's tough_ptr:
--------------%<---------------
#ifndef TOUGH_PTR_H
#define TOUGH_PTR_H
#include <iostream>
template<typename _Tp>
class tough_ptr
{
private:
_Tp* _M_ptr;
public:
explicit
tough_ptr(_Tp* __p = 0) throw() : _M_ptr(__p) { }
tough_ptr(tough_ptr& __a) throw() : _M_ptr(__a._M_ptr) { }
template<typename _Tp1>
tough_ptr(tough_ptr<_Tp1>& __a) throw() : _M_ptr(__a._M_ptr) { }
tough_ptr&
operator=(tough_ptr& __a) throw()
{
_M_ptr = __a._M_ptr;
return *this;
}
template<typename _Tp1>
tough_ptr&
operator=(tough_ptr<_Tp1>& __a) throw()
{
_M_ptr = __a._M_ptr;
return *this;
}
~tough_ptr() {}
const _Tp* get() const { return _M_ptr; }
_Tp&
operator*() const throw()
{
return *_M_ptr;
}
_Tp*
operator->() const throw()
{
return _M_ptr;
}
template<typename _Tp1>
operator tough_ptr<_Tp1>() throw()
{ return tough_ptr<_Tp1>(this->_M_ptr); }
};
template<typename _Tp>
std::ostream& operator<< (std::ostream& in_ostream, const tough_ptr<_Tp>&
in)
{
in_ostream << *(in.get());
return in_ostream;
}
#endif // TOUGH_PTR_H
--------------%<---------------