Why don't smart pointers have the same semantics as plain pointers?
I use more and more BOOST smart pointers instead of plain pointers in my C++ code, and it is incredible how it saves time and prevent bugs! But I was wondering why one couldn't just change the type of a pointer a keep all code as it is, instead of having to change affectation to reset(), for example. E.g., the following code: Foo* ptr_foo; ptr_foo = new Foo; Has now to be changed to: shared_ptr<Foo> ptr_foo; ptr_foo.reset(new Foo); But I'd like it to be: shared_ptr<Foo> ptr_foo; ptr_foo = new Foo; Is there a problem to have shared_ptr<T>::operator=(T*)? Curiously, Nowhere man -- nowhere.man@levallois.eu.org OpenPGP 0xD9D50D8A
On 16/01/06, Pierre THIERRY
Is there a problem to have shared_ptr<T>::operator=(T*)?
As I understand it, it's not allowed so that it's very clear when it's done. Once a pointer ends up in a shared_ptr, there's no way to get it out of one, so independently creating 2 shared_ptrs that both own the same memory location is a recipe for disaster. There's always "shared_ptr<Foo> ptr_foo( new Foo );", which is less typing than either anyways. - Scott
Le Mon, 16 Jan 2006 20:16:14 -0500, me22 a écrit :
Is there a problem to have shared_ptr<T>::operator=(T*)? As I understand it, it's not allowed so that it's very clear when it's done.
OK, but that shouldn't be allowed to be clear when it's done only if there's a risk using this assignation.
Once a pointer ends up in a shared_ptr, there's no way to get it out of one, so independently creating 2 shared_ptrs that both own the same memory location is a recipe for disaster.
Who said it had to be independent? As I see it, the implementation could be: shared_ptr & operator=(T * r) { reset(r); return *this; }
There's always "shared_ptr<Foo> ptr_foo( new Foo );", which is less typing than either anyways.
But only possible at the construction. In any other place, you have to use reset. And the problem is, I have to modify deeply my code to use shared_ptr, and change it back if I stop using them. With the operator=(T*), it would need no more than a modified typedef for the entire code to switch to or from shared_ptr (or from any other type of pointer that supports this operator). Simply, Nowhere man -- nowhere.man@levallois.eu.org OpenPGP 0xD9D50D8A
Pierre THIERRY wrote:
Le Mon, 16 Jan 2006 20:16:14 -0500, me22 a écrit :
There's always "shared_ptr<Foo> ptr_foo( new Foo );", which is less typing than either anyways.
But only possible at the construction. In any other place, you have to use reset. And the problem is, I have to modify deeply my code to use shared_ptr, and change it back if I stop using them.
With the operator=(T*), it would need no more than a modified typedef for the entire code to switch to or from shared_ptr (or from any other type of pointer that supports this operator).
Just replacing shared_ptr<T> with T* seems to require much more than just a typedef. If the goal is to replace boost::shared_ptr<T> with foo::shared_ptr<T>, you might look into traits. -Thorsten
Pierre THIERRY wrote:
Once a pointer ends up in a shared_ptr, there's no way to get it out of one, so independently creating 2 shared_ptrs that both own the same memory location is a recipe for disaster.
Who said it had to be independent? As I see it, the implementation could be:
shared_ptr & operator=(T * r) { reset(r); return *this; }
Yes, but: shared_ptr<Foo> fooptr; Foo* ptr = new Foo; fooptr = ptr; fooptr = ptr; //boom There are thousands of possible bugs like the above that can be caused by an "automatic" shift to shared_ptr - remember, a shared_ptr must be the *unique* owner of a raw pointer.
There's always "shared_ptr<Foo> ptr_foo( new Foo );", which is less typing than either anyways.
But only possible at the construction. In any other place, you have to use reset. And the problem is, I have to modify deeply my code to use shared_ptr, and change it back if I stop using them.
You can avoid that: typedef shared_ptr<Foo> fooptr; fooptr p; //... f = fooptr(new Foo); That doesn't need to change if you change back to: typedef Foo* fooptr; However, that change is unlikely to work (since you'll suddenly have memory leaks at best), but you could at least quite easily change to: typedef mysmartptr<Foo> fooptr;
With the operator=(T*), it would need no more than a modified typedef for the entire code to switch to or from shared_ptr (or from any other type of pointer that supports this operator).
Changing the typedef like that is likely to introduce a huge number of bugs to your code! Remember, when a shared_ptr is given a raw pointer, it takes ownership of that pointer. If anything else still owns that pointer (or multiple shared_ptrs are separately given ownership of the raw pointer), your code is going to perform double deletions. Requiring explicit transfer at least forces you to examine every ownership transfer in the code to make sure it is valid, and to change it if not. Tom
participants (4)
-
me22
-
Pierre THIERRY
-
Thorsten Ottosen
-
Tom Widmer