Skip to main content
gamedev.net
🔒 Locked

Smart pointer question

Started by antareus 13 replies 850+ views
Original Post
antareus
antareus
I know not to use std::auto_ptr inside of a container because auto_ptr's are not CopyConstructible (STL concept). In order to get around this, why can't someone just write their own AutoPtr template class and declare the internal pointer to be mutable? After all, if the pointer is just going to be the owner of a resouce, I don't see a need to use a shared_ptr. A little hacky, yes, but I consider it better than maintaining a reference count.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Shannon Barber
Shannon Barber
The whole problem is that the pointer cannot own the resource if you want to use it with an STL container.
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
chollida1
chollida1
We use std::auto_ptrs along with CComPtr's and all we do is overoad the copy constructor so that a deep copy of pointer is created. Is this not an acceptable solution??

Cheers
Chris
CheersChris
snk_kid
snk_kid
i think the problem is people are not understanding the intended purpose of std::auto_ptr, there is already a hint in its name "auto" as in automatic variable you know the storage class auto that is implicitly declared with variables inside function/block scope that is the default storage class, e.g.

void foo() {   auto int bar; //auto is normally implicitly declared   {      auto int foobar;   }}


So auto_ptr makes heap allocated objects act like variables with storage class of auto, so once the end of the function/block scope is finished its deleted automatically.

auto_ptr's main intent is to be used for RAII techniques & exception code, so for what its intended for its appropriately designed.

note that boost::shared_ptr is in c++ Library TR 1 standard, std::tr1::shared_ptr
SiCrane
SiCrane
Quote:
Original post by antareus
I know not to use std::auto_ptr inside of a container because auto_ptr's are not CopyConstructible (STL concept). In order to get around this, why can't someone just write their own AutoPtr template class and declare the internal pointer to be mutable? After all, if the pointer is just going to be the owner of a resouce, I don't see a need to use a shared_ptr. A little hacky, yes, but I consider it better than maintaining a reference count.


Actually, one of the original forms of the standard library allowed std::auto_ptr to compile inside an STL container without errors or warning, and all seemed well. Then one day someone decided to use an algorithm on the container class, and for lack of a better term, something hit the fan hard.

Consider std::sort() an implementation in pseduo-code might look something like:
std::sort(begin, end) {  if (begin == end) return;  T pivot = get_pivot(begin, end)  iterator middle = partition(begin, end, pivot)  sort(begin, middle)  sort(middle, end)}

This isn't even close to right for a quicksort algorithm, but it illustrates the underlying problem: there's a temp value copy made in the algorithm, which removes one of the stored objects from ownership by the container. And then the recursion removes even more stored objects.

Basically, this a problem that can't be addressed by modifying just std::auto_ptr. You have to create an entire standard library implementation that plays happily with std::auto_ptr like objects that have unusual copy construction semantics. You might be able to create your own std::auto_ptr analogue that can be compiled in a standard container, but be very careful what algorithms and possibly even member functions you use with that container.
Toolmaker
Toolmaker
Well, it doesn't fail when you assign the auto pointer to itself, since it increases the refcount before killing the old pointer.

Secondly, why isn't Reset() exception safe(And for matter of completion, what the hell are hierarchial conversions)?

Toolmaker
 
twanvl
twanvl
    m_Pointer = p;    m_RefCount = new size_t;    *m_RefCount = 1;

If new throws an exception the reference count is not set, while the pointer is. Also, the copy constructor and assignment fail if the object to be copied is not initialized.
I don't know what Polymorphic OOP meant by hierarchial conversions, but your code does not allow the following:
SmartPtr<Derived> d(new Derived);SmartPtr<Base> b = d;

As others have said: use boost::shared_ptr, why reinvent the wheel?
antareus
antareus
Well, I know what an auto_ptr is. And it makes perfect sense why it blows up with sorting. I just find it strange that in order for a container to safely own a pointer and delete it when it is done, that it must be reference counted.

What a pain.

Why not just write STL wrapper classes (like vector_ptr, etc) that handle this fact for you? The ptr suffix is okay, but I'd prefer a name like "PossessiveVector" or the like...something that expresses the fact that the container is responsible for the lifetime of the pointers it holds.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Polymorphic OOP
Polymorphic OOP
Quote:
Original post by twanvl
I don't know what Polymorphic OOP meant by hierarchial conversions

I was refering to standard pointer conversions through a type hierarchy that work with regular pointers and other smart pointer types, such as shared_ptr (and in his case, his smart_ptr implementation doesn't work with pointers of further cv-qualification either).

I.E.

class a { public: virtual ~a() {} };class b : public a {};SmartPtr< b > b_ptr( new b );SmartPtr< a > a_ptr = b_ptr; // Will not work, and no function is provided to make it work// AlsoSmartPtr< const b > const_b_ptr = b_ptr; // Same problem as above


Of course, that doesn't affect its ability to be safely used in a container, but it's another feature which mimmicks the use of regular pointers and adds no runtime cost compared to his current implementation, yet is not supported by the template -- further reason to just use another smart pointer type, such as shared_ptr instead.
Enigma
Enigma
Quote:
Original post by Toolmaker
Well, it doesn't fail when you assign the auto pointer to itself, since it increases the refcount before killing the old pointer.


It NULLs both the pointer and reference count, thus destroying the pointer and leaking both pointer and reference count. Don't just take my word for it, try it:
SmartPtr<T> ptr(new T);ptr = ptr;ptr->func(); // null pointer exception

(disclaimer: I don't have a compiler to actually test that at the moment, but it's not gone midnight and I've had two cups of coffee already, so unless I'm seriously missing something the above should do what I expect).
EDIT: I grabbed and compiler and tested it, and after fixing another error (your constructor-from-T-pointer uses uninitialised values) it does indeed demonstrate the behaviour I expected.

Enigma

[Edited by - Enigma on December 24, 2004 9:56:47 AM]
Toolmaker
Toolmaker
Ok, thanks for the replies. I'll fix those so at least it works. The reason I wrote the smart pointer was mainly a learning experience. I needed a smart pointer, and decided to write my own so as a nice learning experience.

I'll fix those errors which I can fix for now. How would I go on fixing the errors with the hierachical conversions?

Toolmaker
 

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.