smart pointer array - c++

I have created a smart pointer class like:
template <class T>
class Owner
{
T* m_p;
public:
Owner(T *p=0) : m_p(p) {}
~Owner() { if (m_p) delete m_p; }
T* operator ->() { return m_p; }
T& operator *() { return *m_p; }
// other members.
};
It works well (resembles to the auto_ptr in boost library), but now I have the requirements that I want to store an dynamic array of smart pointers in an obj, and it must support:
1) insert new smart pointer into the smart pointers array to let the array resize and acquire the ownership of the new obj,
2) delete one smart pointer on the fly and the resource get freed,
3) when finalizing the array, all objects get deleted.
I was thinking using std::vector<Owner<T> >, but seems c++ best practice suggests not storing smart pointers in std containers, because copy/assignment behaviors, so what other things can I employ to implement this? something like the OwnerArr in the below example:
class Adapter;
class Computer
{
public:
Computer() {}
~Computer() { // adapters get freed automatically here. }
void insertAdapter(Adapter* pAdapter) { m_adapters->appendOne(pAdapter); }
OwnerArr<Adapter> m_adapters;
};
Thanks in advance!

You can't store your Owner, or std::auto_ptr (which you shouldn't use anyway, since it's deprecated), in a standard container because they are not really copyable.
In C++11, there's std::unique_ptr: a single-ownership smart pointer to replace auto_ptr, which is movable but not copyable. This can be moved or emplaced into any container, as long as you don't need to do anything that involves copying it. If you need multiple pointers to share ownership of the same object, then you can use std::shared_ptr instead.
If you're stuck with an older language version for some reason, then Boost can give you smart pointers, including a shared_ptr very similar to the standard one, or pointer containers similar to your OwnerArray.
If you do decide to roll your own resource management classes, always remember the Rule of Three. The classes you show have implicitly generated copy constructors and copy-assignment operators which can cause two pointers to own - and try to delete - the same object, which is very bad. You need to either prevent copying (by deleting these functions, or (pre-2011) declaring them private with no implementation), or implement some kind of safe copy semantics.

Related

Looking for a smart pointer which will copy the underlying resource when copying the smart pointer itself

Motivation
Imagining that there is a very large class A, and I wanna store it in a vector and I also want the vector to be copyable. Thus, smart pointer like std::shared_ptr and std::unique_ptr would not be nice choices. I know I could store objects of A in std::vector<A> directly. But as I said, A is a very large class. And since elements of std::vector<A> reside continuously in memory, there is a big chance that std::vector<A> needs to reallocate memory if I update it frequently. So, I need a "smart pointer" (let's say copyable_ptr) which will copy the underlying resource when copying the smart pointer itself. Then I could use std::vector<copyable_ptr<A>> to manage objects of A.
Here is a snippet template class of copyable_ptr:
template <typename T> class copyable_ptr {
public:
explicit copyable_ptr(T *p) : p(p) {}
copyable_ptr(copyable_ptr const &rhs) : p(new T(*rhs.p)) {}
copyable_ptr(copyable_ptr &&rhs) : p(rhs.p) { rhs.p = nullptr; }
~copyable_ptr() { delete p; }
copyable_ptr &operator=(copyable_ptr rhs) {
swap(rhs);
return *this;
}
void swap(copyable_ptr &rhs) {
using std::swap;
swap(p, rhs.p);
}
T &operator*() const { return *p; }
T *operator->() const { return &this->operator*(); }
/* other members */
private:
T *p;
};
template <typename T>
inline void swap(copyable_ptr<T> &lhs, copyable_ptr<T> &rhs) {
lhs.swap(rhs);
}
Question
Is there similar class that I can use directly or should I write my own or Is there any other appropriate solutions to store big class in container?
Edit
I think I should explain myself more clearly. A is a very large class, and I wanna use std::vector to manage objects of A. Basically, there are four options to do the job:
std::vector<std::shared_ptr<A>> a1; // #1
std::vector<std::unique_ptr<A>> a2; // #2
std::vector<A *> a3; // #3
std::vector<A> a4; // #4
I do not want to share objects of A, which makes #1 inappropriate. The vector will not be copyable in #2, and I have to take care of memory management manually
in #3. So, only #4 lefts.
However, what I don't like about #4 is when size of a4 reaches its capacity, reallocating happens. Double size of a4 will be reserved (as I said, A is a very large class, isn't it inappropriate to reserve so much continuous memory in heap just for potential usage?). And What's worse is we perhaps need to move every single element of a4 to the newly allocated memory from old memory location. Another backward of #4 that I forgot to mention when I asked the question is it's not polymorphic support.
So, if I use std::vector<copyable_ptr<A>> to manage objects of A, all the problems I mentioned above seems be handled properly. All you need is a well designed copyable_ptr class, and that's what I'm looking for.
Yes, there is such a thing: it's called the class itself.
The whole purpose of a smart pointer is to provide a reference-counted handle for an object, that can be passed around, without copying the underlying object, and automatically destroy the object when the reference count goes down to 0, and the last smart pointer referencing the object goes out of scope, and it gets destroyed (with certain variations of reference-counting semantics between shared_ptr, unique_ptr, et al).
If you want to have some kind of a pointer to an object that copies it, when copying the pointer, you don't need a pointer for that. Just use the object directly, by value. Every time you copy it, you're guaranteed to copy the object, by definition.
Having some kind of pointer, around, adds absolutely nothing of value. You want to use the object directly, copy it when needed, etc... Just use the object.
As far as I know, there is no such smart pointer in the standard library. Your copyable_ptr seems to do the job. I've used such things in the past, though for polymorphic classes instead of just really big classes.
Not exactly the answer to question, but if this:
However, what I don't like about #4 is when size of a4 reaches its capacity, reallocating happens.
is your main concern and if your are Ok with storing your classes in non-contiguous memory with slightly slower direct access by index, you can use std::deque instead of std::vector.

Store weak pointer to self

I work with a codebase that was partially implemented by someone who was in love with overly complex solutions to simple problems (e.g. template classes with two parameters that were only ever instantiated for one pair of types). One thing she did was to create objects in a smart pointer, and then have the object store a weak pointer to itself.
class MyClass {
//...
boost::weak_ptr<MyClass> m_self;
//...
};
boost::shared_ptr<MyClass>
Factory::Factory::Factory::CreateMyClass() {
boost::shared_ptr<MyClass> obj(new MyClass(...));
boost::weak_ptr<MyClass> p(obj);
obj->storeSelfPointer(p);
return obj;
}
The class then proceeds to use m_self by locking it and passing around the resulting shared pointer.
For the life of me, I cannot fathom what she was trying to accomplish. Is there some pattern or idea that would explain this implementation? It looks to me like this is completely pointless and I'd like to refactor it away.
EDIT: I should mention that none of the places that use the resulting smart pointer obtained from locking m_self actually retain the smart pointer.
A possible use of this "design" could be to use m_self.lock() to generate shared pointers from this.
If you remove this weak pointer member, the reference count hold by the generated shared pointer from this would be incorrect.
It achieves the same than std::enable_shared_from_this, interestingly enough, cppreference.com mentions this design :
A common implementation for enable_shared_from_this is to hold a weak
reference (such as std::weak_ptr) to this. The constructors of
std::shared_ptr detect the presence of an enable_shared_from_this base
and assign the newly created std::shared_ptr to the internally stored
weak reference
And the C++ standard, section § 20.8.2.4 10 , mention the same possible implementation :
The shared_ptr constructors that create unique pointers can detect the
presence of an enable_shared_- from_this base and assign the newly
created shared_ptr to its
__weak_this member
Possible Refactoring :
If you are using C++11, you can remove the std::weak_ptr member, and publicly inherits from std::enable_shared_from_this<T>. You should retrieve a shared pointer from this by calling shared_from_this().
If you are not using C++11 but can use boost, use boost::enable_shared_from_this, see the boost documentation. You should retrieve a shared pointer from this by calling shared_from_this().
If you are not using C++11, and can't use boost, you can bring the proposed implementation of the standard to your code base, it is short enough :
Code : (copied from § 20.8.2.4 - 11, remove leading underscores, and you probably want to rename it)
template<class T> class enable_shared_from_this {
private:
weak_ptr<T> __weak_this;
protected:
constexpr enable_shared_from_this() : __weak_this() { }
enable_shared_from_this(enable_shared_from_this const &) { }
enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; }
~enable_shared_from_this() { }
public:
shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); }
shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); }
};
And use shared_from_this() to make a shared pointer. If you do copy this code, note that constructing shared pointers from this by other means would not work. The shared pointers constructors need to be modified (as explain by the standard quote above).

Smart pointer that does transfer of ownership and is not shared when C++11 is not an option

Currently I am solving my problem with boost::shared_ptr but the semantics is not quite right, since I am "transplanting" members from one object to another. I was looking through this list but it didn't yield too much. Same goes for my brief google searches.
Essentially I am looking for a unique_ptr implementation that works with my gcc4.2 (Hence the restriction to not use C++11)
You could stick with std::auto_ptr until Boost implements unique_ptr on top of the new Boost Move library (C++03 compatible).
See this mailing list traffic d.d. November 10th 2011: http://boost.2283326.n4.nabble.com/smart-ptr-Inclusion-of-unique-ptr-td4021667.html
Edit And Boost Interprocess has a uniqe_ptr<> class template floating around:
http://www.boost.org/doc/libs/1_48_0/doc/html/boost/interprocess/unique_ptr.html
Depending on what exactly you want, you might consider using boost::scoped_ptr. It is very similar to std::unique_ptr, but it cannot be moved (because C++03 doesn't know about move-semantics). It can, however be swapped. So, when you want to transfer ownership, just do this:
boost::scoped_ptr<T> dummy;
dummy.swap(my_ptr);
// now you have basically transferred ownership from my_ptr to dummy
Use std::auto_ptr<..>, it has exactly what you need.
llvm::OwningPtr - it has take method to take ownership.
boost::shared_ptr with custom deleter.
This is something I used in unit test to simulate Corba _var class behaviour.
struct CondDel {
bool doDel;
CondDel() : doDel(true) {
}
template<typename T>
void operator()(T* p) {
if (doDel)
delete p;
}
};
class MyCorbaObj_var : public boost::shared_ptr<_objref_MyCorbaObj> {
public:
MyCorbaObj_var(_objref_MyCorbaObj* p) : boost::shared_ptr<_objref_MyCorbaObj>(p, CondDel()) {
}
_objref_MyCorbaObj* _retn() {
CondDel* cd = (CondDel*)_internal_get_deleter(typeid(CondDel));
cd->doDel = false;
return get();
}
};
If you want copying objects of your class to make new copies of the pointed-to items, then no kind of pointer (auto_ptr, shared_ptr or naked pointer) will do what you want without some extra work on your part. You will need to manage the copying yourself. Be sure you implement a copy constructor and assignment operator so that they clone the pointed-to items and store the new pointers in the destination object. If you do this, auto_ptr and shared_ptr will both work just fine for you.

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.

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.