Implementing unique_ptr: Deleting non-allocated objects - c++

My goal here is to implement a simple version of unique_ptr which offers only a constructor, destructor, ->, *, and release().
However, I don't know what to do in the case where a unique_ptr is initialized using a non-allocated pointer.
eg
int i = 0;
unique_ptr<int> p{&i};
If the unique_ptr simply calls delete on it owned pointer, this will produced undefined (and undesirable) behavior, at least as far as I know. What can I do to prevent this?
EDIT: My attempt at the problem is as follows...
template<typename T>
class Uptr
{
public:
Uptr<T>(T* pt) : mp_owned{pt} {}
~Uptr<T>() {delete mp_owned;}
Uptr<T>(const Uptr<T>&) = delete;
Uptr<T>& operator=(const Uptr<T>&) = delete;
T& operator*() const {return *mp_owned;}
T* operator->() const {return mp_owned;}
T* release() {return mp_owned;}
private:
T* mp_owned;
};

You cannot check programmatically how a pointer value was obtained. In your situation (which is highly representative of large parts of real programming!), the solution is to document your interface to require that the pointer value be deletable. You place a precondition on your users, which requires that your users read the documentation and follow it, and you do not and cannot provide in-language methods for validating those preconditions. You pass the burden on to your users.
Such precondition burdens always form a kind of "technical debt", and you want to avoid it as much as you can (but perhaps not at the expense of runtime cost). For example, in the standard library we would strongly discourage the use of the ownership-taking constructor of unique_ptr and instead as the user to use make_unique, which has no preconditions and results in a valid unique_ptr value. That design is exemplary for how you would manage technical debt in the real world.

Unfortunately, there is nothing you can do about this: the ownership of the object must be transferred to unique_ptr<T>, which is not possible if you use addresses of objects in global, static, or automatic areas.
The implementation from the standard library, i.e. std::unique_ptr<T,Deleter>, takes a deleter parameter, which you can use to not delete anything. However, this use is highly questionable, because in this situation you do not need unique_ptr at all.

Related

Is it sensible to use shared_ptr instead of unique_ptr as class member just to avoid implicit copy constructor deletion?

I would like to preserve the default copy-constructor of a large-ish (but say not particularly complex*) class, but ideally would like to replace some raw pointer member with a smart-pointer alternative.
unique_ptr seems to be the default for this, but it implicitly deletes the copy constructor for my class.
shared_ptr instead would allow me to preserve the class' copy constructor. Could that likely be a good reason to simply stick to shared_ptr, even if I do not genuinely want to 'share' the resource; I really only want to preserve the readily available copy constructor (annoying to write a manual copy constructor for the entire class, just to replace a pointer with a unique_ptr), just as I had it when I still used raw pointer.
Searching for when to use shared_ptr vs. unique_ptr, I never see the simple preservation of the copy-constructor indicated as a possible key reason to use shared_ptr (possible exception https://stackoverflow.com/a/16030118/3673329 but not giving any detail), but I also do not directly see any reason why this could not be a valid choice.
I reckon shared_ptr may be a bit more resource intensive, but assume my case where this is no real problem.
*In particular, the default/shallow copying of the class was fine for my purposes as long as I used raw pointer members instead of smart ones.
If the only reason to use std::shared_ptr is to retain default copy constructibility of your class, you prioritize ease of use over the intended semantics of your class with respect to resource handling. In my opinion, you have to decide up front whether the class shall share its resources or exclusively own it. If you are unsure whether the class should share its resources with copied instances or not, something else in the design might at least be suspicious.
There might be an exception to this guideline, and that is std::shared_ptr<const YourType>. In the case of read only access, it might be acceptable to use such a technique to allow for default copy construction (although in a different context, here is where Sean Parent says that std::shared_ptr<const T> is acceptable to obtain value semantics).
Note one further implication: if you share a std::shared_ptr instance, you are not only sharing state and functionality of the pointee, you also share lifetime control. If the latter is not what you intend, just share a reference (preferable) or a raw pointer to the pointee, with access e.g. via a getter-like member function. If the consuming parts of your class can't know whether the pointee is still alive or has already been destroyed, a std::weak_ptr could be an option.
There is still a great deal of advantage in using a unique_ptr and providing the missing copy operations manually.
You get the correctness guarantees plus an easy customisation point for inner object cloning.
example:
#include <memory>
struct LargeImplObject
{
int x[1000];
};
struct CopyableHandle
{
using impl_class = LargeImplObject;
using implementation_type = std::unique_ptr<impl_class>;
CopyableHandle()
: impl_(construct())
{}
CopyableHandle(CopyableHandle&&) noexcept = default;
CopyableHandle& operator=(CopyableHandle&&) noexcept = default;
CopyableHandle(CopyableHandle const& other)
: impl_(other.clone())
{}
CopyableHandle& operator=(CopyableHandle const& other)
{
impl_ = other.clone();
return *this;
}
// note: no destructor
private:
// customisation points
static auto construct() -> implementation_type
{
return std::make_unique<impl_class>();
}
auto clone() const -> implementation_type
{
return std::make_unique<impl_class>(*impl_);
}
implementation_type impl_;
};
int main()
{
auto a = CopyableHandle();
auto b = a;
auto c = std::move(a);
a = std::move(c);
}

Missing shared_ref

While working with std::shared_ptr a lot I kind of miss a shared_ref implementation. That is a specialization of shared_ptr, which guarantees, that it never wraps a nullptr (given right usage, of course).
I kind of wonder why it is not in the C++11 standard. Are there any mayor problems when implementing it? On the top of my head I cannot think of any.
EDIT:
I would expect to have an interface similar to:
template <typename T>
class shared_ref {
public:
shared_ref( T&& ref );
T& get();
T* operator&() const;
template< class Y >
void reset( Y&& obj );
long use_count() const;
bool unique() const;
void swap( shared_ref& r );
};
Are there any mayor problems when implementing it?
Here's one: you can't take ownership of a reference. The whole point of a smart pointer is to claim ownership of the pointer itself. shared_ref can't work because you can't control the lifetime of a reference.
And no, this isn't going to fly either:
shared_ref( T&& ref ) : p(&ref) {}
The user may have given you a stack variable, which now means you have "shared" ownership between this object and a stack variable. And stack variables cannot share ownership with something.
You can only control the lifetime of a pointer. And pointers can be NULL. Therefore, the only thing you can do is a runtime check to see if a pointer is NULL.
The absolute best you can do is an interface equivalent to shared_ptr except that it has no default constructor and throws in the event of being given NULL. Is that really worth creating a whole new pointer type over?
The C++ Core Guidelines support library has the not_null template, which can be applied to most pointer-like types. So you can use not_null<shared_ptr> when you want to verify that a pointer isn't NULL, but only once when it enters use. After the initial creating of the pointer, it doesn't need to check again.
Granted, you can't force other people to use them, but use of the type consistently will resolve the issue.
There are only two ways for a shared_ptr to be null - either it was default constructed, or it was assigned a null value at some point. Since you already agree it doesn't make sense to default construct your hypothetical shared_ref class, that leaves only the second condition.
If you tried to assign a nullptr to your shared_ref object, what would you expect to happen? Should it throw an error? It's trivial to do the same thing with a regular shared_ptr using a simple template function:
template<typename T>
T* notnull(T* ptr)
{
if (ptr == std::nullptr)
throw std::invalid_argument(std::string("nullptr"));
return ptr;
}
std::shared_ptr<int> pint = notnull(GetIntPtr());
Generally things aren't added to the standard unless there's a compelling need with no easy workarounds.

C++ tree of pointers template question

I've just come across a nice STL-like tree container class written by Kasper Peeters:
http://tree.phi-sci.com/
However, because it's STL-like, it's geared towards having a single class type in the tree; i.e. template <class T>. The trouble is, like STL-lists, if it suffers from the polymorphic class problem, in that the objects in the tree that are pointers to heap based objects (like pointers to a base class), aren't destroyed when nodes are deleted.
So, my options:
1: Use a tree of boost::shared_ptr, although this is more expensive/overkill than I'd like.
2: Write a little pointer wrapper like the one I've written below. The idea being that it wraps a pointer, which when it goes out of scope, deletes its pointer. It's not ref counted, it's just guarantees the pointer destruction.
template<class T>
class TWSafeDeletePtr
{
private:
T *_ptr;
public:
TWSafeDeletePtr() : _ptr(NULL) {}
TWSafeDeletePtr(T *ptr) : _ptr(ptr) {}
~TWSafeDeletePtr()
{
delete _ptr;
}
T &operator=(T *ptr)
{
assert(!_ptr);
delete _ptr;
_ptr=ptr;
return *ptr;
}
void set(T *ptr)
{
*this=ptr;
}
T &operator*() const { return *_ptr; }
T *operator->() const { return _ptr; }
};
3: Write my own allocator which allocates the node objects from a pool in the allocate() and deletes the pointed to memory in the deallocate().
4: Specialise the code to make a tree of pointers, avoiding the initial allocation and copy construction, plus innately knowing how to delete the pointed-to data.
I already have option 2 working, but I'm not really happy with it, because I have to actually insert an empty ptr to begin with, then set() the pointer when the insert returns an iterator. This is because the tree uses copy construction, and hence the temporary object passed on the stack will ultimate delete the pointer when it goes out of scope. So I set the pointer upon return. It works, it's hidden, but I don't like it.
Option 3 is looking like the best candidate, however I thought I'd ask if anyone else has already done this, or has any other suggestions?
Ok, I'ved decided to go with option 1 (tree of shared_ptrs), mainly because it's using standard libraries, but also because the extra refcount per node won't break the bank. Thanks for the replies everyone :)
Cheers,
Shane
I don't like the allocator version, because allocators are supposed to allocate memory, not construct objects. So there's no guarantee that the number of requested allocations to the allocator matches the number of objects to be constructed; it would depend on the implementation whether you get away with it.
The tree calls the copy constructor on an inserted or appended value after the allocator has allocated the memory for it, so you would be hard pressed to write something which worked with polymorphic objects - alloc_.allocate doesn't know the runtime type of x before the constructor is called (lines 886 on):
tree_node* tmp = alloc_.allocate(1,0);
kp::constructor(&tmp->data, x);
Also looking at the code it doesn't seem to use assignment at all, and your wrapper only supplies the default copy constructor, so I can't see any of your suggested mechanisms working - when a node is assigned to the same value as it already holds with this code called (lines 1000 on):
template <class T, class tree_node_allocator>
template <class iter>
iter tree<T, tree_node_allocator>::replace(iter position, const T& x)
{
kp::destructor(&position.node->data);
kp::constructor(&position.node->data, x);
return position;
}
your smart pointer would destruct their referent when their destructor is called here; you may get away with it by passing a reference counted pointer instead (so x doesn't destroy its referent until it goes out of scope, rather than the position.node->data destructor destroying it).
If you want to use this tree, then I would either use it as an index into data owned elsewhere rather than the tree owning the data, or stick with the shared_ptr approach.
[Edit] Shane has chosen to go with the boost::shared_ptr solution and has pointed out that he needs to store polymorphic base pointers. Should memory/processing efficiency ever become a concern (after profiling, of course), consider a base pointer wrapper with safe copying behavior (e.g., deep-copying the pointee through a clone method) and the fast swap idiom shown in #5. This would be similar to suggested solution #2, but safe and without making assumptions on the data type being used (ex: trying to use auto_ptr with containers).
I think you should consider option #5.
1: Use a tree of boost::shared_ptr,
although this is more
expensive/overkill than I'd like.
First of all, do you realize that any linked structure like std::list, std::set, std::map requires a separate memory allocation/deallocation per node but doesn't require copying nodes to do things like rebalance the tree? The only time the reference counter will amount to any processing overhead is when you insert to the tree.
2: Write a little pointer wrapper like
the one I've written below. The idea
being that it wraps a pointer, which
when it goes out of scope, deletes its
pointer. It's not ref counted, it's
just guarantees the pointer
destruction.
For this tree you might be able to get away with it since you have the tree implementation, but it's a heavy assumption. Consider at least making the pointer wrapper non-copyable so that you'll get a compiler error if you ever try to use it for something which does copy node elements.
3: Write my own allocator which
allocates the node objects from a pool
in the allocate() and deletes the
pointed to memory in the deallocate().
If it's an STL-compliant memory allocator, it should not be making such assumptions about the memory contents in deallocate. Nevertheless, writing a fast memory allocator which can assume fixed allocation sizes can really speed up any linked structure. Writing a fast memory allocator that consistently outperforms malloc/free is non-trivial work, however, and there are issues to consider like memory alignment.
4: Specialise the code to make a tree
of pointers, avoiding the initial
allocation and copy construction, plus
innately knowing how to delete the
pointed-to data.
Making a wrapper for the tree is probably the most robust solution. You'll have full control over when to insert and remove elements (nodes) and can do whatever you like in the mean time.
Option #5: just store the element directly in the tree and focus on making the element fast.
This is your best bet if you ask me. Instead of map<int, ExpensiveElement*> or map<int, shared_ptr<ExpensiveElement> >, consider simply map<int, ExpensiveElement>.
After all, you obviously want the tree to be the memory manager (deleting a node deletes the element). That happens when we avoid the indirection of a pointer to the element already.
However, your concern seems to be the overhead of the copy-in policy of insert (copy ctor overhead on ExpensiveElement). No problem! Just use operator[] instead of insert:
map<int, ExpensiveElement> my_map;
// default constructs ExpensiveElement
// and calls ExpensiveElement::do_something().
// No copies of ExpensiveElement are made!
my_map[7].do_something();
Tada! No copying, no need to worry about proper destruction, and no memory allocation/deallocation overhead per element.
If default constructing ExpensiveElement won't suffice, then consider making default construction super cheap (practically free) and implement a swap method.
map<int, ExpensiveElement> my_map;
// construct an ExpensiveElement and swap it into the map
// this avoids redundant work and copying and can be very
// efficient if the default constructor of ExpensiveElement
// is cheap to call
ExpensiveElement element(...);
my_map[7].swap(element);
To make the default construction super cheap and allow for a swap method, you could implement a fast pimpl on ExpensiveElement. You can make it so the default ctor doesn't even allocate the pimpl, making it a null pointer, while the swap method swaps the two pimpls of ExpensiveElement. Now you have super cheap default construction and a way to swap properly constructed ExpensiveElements into the map, avoiding the redundancy of deep copies all together.
What if ExpensiveElement cannot have a default ctor?
Then make a wrapper which does. The approach can be similar to the pointer wrapper you suggested, except it will be a complete class with valid (safe) copying behavior. The copy ctor can deep copy the pointee, for example, if reference counting is undesired. The difference may sound subtle, but this way it's a very safe and complete solution which doesn't make assumptions about how the tree is implemented; safe and general like boost::shared_ptr but without the reference counting. Just provide a swap method as your one and only means to shallow swap data without requiring a deep copy and use it to swap things into the tree.
What if we need to store polymorphic base pointers?
See answer immediately above and modify the wrapper to call something like clone (prototype pattern) to deep copy the pointee.
First of all, you could benefit from move semantics here. If you have access to C++0x.
Otherwise, the Boost Pointer Container library has solved the issue of the STL containers of pointers by... recoding it all.
Another issue with containers of pointers that you did not mention is the copy of the container. In your case the original container and its copy both point to the same objects, so changing one will not change the other.
You can of course alleviate this by writing a proxy class which wraps the pointer and provides deep copying semantic (clone method in the object wrapped). But you will then copy the data more often that if the container is pointer aware.... it's less work though.
/// Requirement: T is a model of Cloneable
template <class T>
class Proxy
{
template <class> friend class Proxy;
public:
// Constructor
Proxy(): mPointer(0) {}
explicit Proxy(T* t): mPointer(t) {}
template <class U>
explicit Proxy(std::auto_ptr<U> t): mPointer(t.release()) {}
template <class U>
explicit Proxy(std::unique_ptr<U> t): mPointer(t.release()) {}
// Copy Constructor
Proxy(Proxy const& rhs):
mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}
template <class U>
Proxy(Proxy<U> const& rhs):
mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}
// Assignment Operator
Proxy& operator=(Proxy const& rhs)
{
Proxy tmp(rhs);
this->swap(tmp);
return *this;
}
template <class U>
Proxy& operator=(Proxy<U> const& rhs)
{
Proxy tmp(rhs);
this->swap(tmp);
return *this;
}
// Move Constructor
Proxy(Proxy&& rhs): mPointer(rhs.release()) {}
template <class U>
Proxy(Proxy<U>&& rhs): mPointer(rhs.release()) {}
// Move assignment
Proxy& operator=(Proxy&& rhs)
{
Proxy tmp(rhs);
this->swap(tmp);
return *this;
}
template <class U>
Proxy& operator=(Proxy&& rhs)
{
Proxy tmp(rhs);
this->swap(tmp);
return *this;
}
// Destructor
~Proxy() { delete mPointer; }
void swap(Proxy& rhs)
{
T* tmp = rhs.mPointer;
rhs.mPointer = mPointer;
mPointer = tmp;
}
T& operator*() { return *mPointer; }
T const& operator*() const { return *mPointer; }
T* operator->() { return mPointer; }
T const* operator->() const { return mPointer; }
T* release() { T* tmp = mPointer; mPointer = 0; return tmp; }
private:
T* mPointer;
};
// Free functions
template <class T>
void swap(Proxy<T>& lhs, Proxy<T>& rhs) { lhs.swap(rhs); }
Note that as well as providing deep-copying semantics, it provides deep-constness. This may or may not be to your taste.
It would also be good taste to provide equivalent to static_cast and dynamic_cast operations, this is left as an exercise to the reader ;)
It seems that the cleanest solution would be a container adaptor in the style of Boost Pointer Container. This would smooth the syntax a lot as well. However writing such an adaptor is tedious and repetive as you would have to "lift" typedefs and repeat every member function of the class that is to be adapted.
It looks like option 1 is probably the best. shared_ptr is very common and most people should know how it works. Is there a problem with the syntax map_obj[key].reset(new ValueType);?
Unless you have measurement data that your wrapper for option 2 is a significant savings in use compared to shared_ptr, shared_ptr seems safer since people will know about its semantics right away.
Option three seems complex for what it provides. You need to implement the allocate/construct and deallocate/destruct pairs, and make sure that if a node is copied around it will not have deletion problems.
Option four is probably the second-best option. I wouldn't suggest using it unless profiling shows that the shared_ptr operations really are that expensive though, since this requires reinventing code that's already been written and debugged in the standard library.
I'ved decided to go with option 1 (tree of shared_ptrs), mainly because it's using standard libraries, but also because the extra refcount per node won't break the bank. Thanks for the replies everyone :)
1.
I already have option 1 working, but I'm not really happy with it, because I have to actually insert an empty ptr to begin with, then set() the pointer when the insert returns an iterator. This is because the tree uses copy construction, and hence the temporary object passed on the stack will ultimate delete the pointer when it goes out of scope. So I set the pointer upon return. It works, it's hidden, but I don't like it.
Until there is at least one copy of the same shared_ptr, pointed object won't be destroyed so there is no problem you writing about.
2.Your class is pointless. Use shared_ptr.
3.The allocator would have to know what kind of object to create when asked for a piece of bytes, this is not well solution.
4.Too much complications.
I suggest solution 1.

Returning reference to a pointer- C++

Consider the following class.
class mapping_items
{
public:
mapping_items(){}
void add(const mapping_item* item) {
items_.push_back( item );
}
size_t count() const{
return items_.size();
}
const mapping_item& find(const std::string& pattern){
const mapping_item* item = // iterate vector and find item;
return *item;
}
private:
mapping_items(const mapping_items&); // not allowed
mapping_items& operator=(const mapping_items&); // not allowed
std::vector<const mapping_item*> items_;
};
C++ FAQ says,
Use references when you can, and
pointers when you have to.
So in the above example, should I return const mapping_item& or const mapping_item* ?
The reason why I chose mapping_item& is because there will be always a default return value available. I will never have null returns. So a reference makes it clear that it can't have nulls. Is this the correct design?
There is a problem - what happens if your find() function fails? If this is expected never to happen, you are OK returning a reference (and raise an exception if it happens despite the fact it shouldn't). If on the other hand it may happen (e.g. looking up a name in an address book), you should consider returning a pointer, as a pointer can be NULL, indicating the find failed.
This is seems like an appropriate design choice to me - like the C++ FAQ states - uses references when you can. IMO, unnecessary use of pointers just seems to make code harder to understand.
Yes, it's the correct design. Clients can rely on values being non-null.
On a related note, some other class is responsible for managing the lifetime of mapping_item's?
Pointers and ownership easily introduces memory leaks or worse. You might want to consider whether you actually need to store pointers, or if you can get away with copying mapping_item's instead, to avoid memory leaks. However, pointers are necessary if you need to manage subclassed mapping_item's. Pointers are advisable if instances are large or need to be shared.
If you really need pointers, consider using boost::shared_ptr<> rather than raw pointers, both inside your class and as parameter types to e.g. the add() function.
Some people say, and I agree,
use pointers if value can be NULL
and references otherwise
As to your example, I'd probably go for return const mapping_item;, so by value, to avoid having a reference to a temporary, and hope for my compiler to optimize copying away.

Pointer container class which can't be copied by value

I need a smart pointer for my project which can be send to several methods as parameter. I have checked auto_ptr and shared_ptr from boost. But IMO, that is not suitable for my requirements. Following are my findings
auto_ptr : When passed to another method, ownership will be transferred and underlying pointer will get deleted when that method's scope ends. We can workaround this by passing auto_ptr by reference, but there is no compile time mechanism to ensure it is always passed by reference. If by mistake, user forgot to pass a reference, it will make problems.
boost::shared_ptr : This looks promising and works correctly for my need. But I feel this is overkill for my project as it is a very small one.
So I decided to write a trivial templated pointer container class which can't be copied by value and take care about deleting the underlying pointer. Here it is
template <typename T>
class simple_ptr{
public:
simple_ptr(T* t){
pointer = t;
}
~simple_ptr(){
delete pointer;
}
T* operator->(){
return pointer;
}
private:
T* pointer;
simple_ptr(const simple_ptr<T>& t);
};
Is this implementation correct? I have made copy constructor as private, so that compiler will alert when someone tries to pass it by value.
If by chance the pointer is deleted, delete operation on the destructor will throw assertion error. How can I workaround this?
I am pretty new to C++ and your suggestion are much appreciated.
Thanks
Please use boost::scoped_ptr<> as suggested by Martin York, because it:
Does exactly what you want (it's a noncopyable pointer)
Has no overhead above that of a standard C pointer
Has been carefully crafted by super-intelligent C++ wizards to make sure it behaves as expected.
While I can't see any problems with your implementation (after applying the changes suggested by ChrisW), C++ has many dark corners and I would not be surprised if there is some obscure corner case which you, I and the others here have failed to spot.
What you have done is boost::scoped_ptr
Please also read comment by j_random_hacker.
Is this implementation correct? I have made copy constructor as private ...
You could do the same for the assignment operator:
simple_ptr& operator=(const simple_ptr<T>& t);
A const version of the dereference operator might be useful too, and, smart pointers usually define the other kind of dereference operator as well:
const T* operator->() const { return pointer; }
const T& operator*() const { return *pointer; }
T& operator*() { return *pointer; }
If by chance the pointer is deleted, delete operation on the destructor will throw assertion error. How can I workaround this?
Do you mean, if I do this:
//create instance
Car* car = new Car;
//assign to smart ptr
simple_ptr<Car> ptr(car);
//explicit delete
delete car;
//... assertion when ptr is destroyed ...
A way (I don't know if it's a good way) to prevent that is to declare the constructor, and/or the destructor, and/or the delete operator of the T class as private, and say that simple_ptr is a friend of the T class (so that only the simple_ptr class can create and/or destroy and/or delete instances of T).
Marking the new operator as private in T class seems to be impossible as I have to modify all the classes which will be used with simple_ptr
Yes that's true: to do my suggestion immediately above, you would need to modify the class definitions.
If your question is "how can I make double deletes impossible, without modifying class definitions?" then I think the answers are:
You can't: it's up the application code (which uses these classes) to be careful
You can: by providing your own heap manager i.e. your own implementation of global operator new and global operator delete and, in your smart_ptr code, interrogate your heap manager to see whether this incarnation of this pointer is still allocated, before you delete it
To answer your first question, the best assurance you can get that this is correct is to implement a test harness around it to do some simple task, and make sure you get the behavior you expect. For me, that is far better comfort the code is right than the opinion of some random person reading it.
As for your second question, you work around delete throwing an assertion error by setting pointer to some marker value after you delete it the first time. Something like:
if (pointer) {
delete pointer;
pointer = NULL;
} else {
error("Attempted to free already freed pointer.");
}
The problem you're going to run into here is that your overloaded -> operator returns the value of the pointer, which means whoever you return this to can also call delete, causing the check I propose above not to work. For example:
simple_ptr<int> myPtr = someIntPointer;
...
delete myPtr.operator->(); /* poof goes your pointered memory region */
I might recommend that you not rely on the operator-> overloading, and just require that those using this class call a method that dereferences the pointer internally before passing that value back to the user.
Hope this helps.
You should user a boost::scoped_ptr<> as has been mentioned already.
In general though, if you need to make a class non-copyable, you should inherit from boost::noncopyable, i.e.
#include <boost/utility.hpp>
class myclass : boost::noncopyable
{
...
};
This does all the work of making it non-copyable and is nicely self-documenting.
You've got two choices:
boost::scoped_ptr already detailed by j_random_hacker, because it's non-copyable (doesn't share ownership like shared_ptr) and non-movable (doesn't transfer ownership like auto_ptr. auto_ptr has a copy constructor, but that one does not copy. It moves the original pointer to *this). boost::scoped_ptr is exactly what you need.
const auto_ptr doesn't allow transfer of ownership. And take your parameter by reference to const (auto_ptr<T> const&). If the writer of a function accepts by value instead, it still won't work if you try passing a const auto_ptr, because its copy constructor needs a non-const auto_ptr.
Until C++1x, boost::scoped_ptr is the best choice for your needs, or a const auto_ptr if you have to use official standard stuff (read this). In C++1x, you can use std::unique_ptr as a better alternative to auto_ptr, because you have to explicitly state when you want to transfer ownership. Trying to copy it will result in a compile time error. unique_ptr is detailed a little in this answer.
I've seen sometimes usage of simple DISABLE_COPY macros:
#define DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
So it's a common practice to define copy constructor and assignment operator as private for your task.