Problem with home-made auto_array!

Started by
34 comments, last by Rydinare 15 years, 2 months ago
In fairness, auto_ptr is dangerous because transfer of ownership is almost never what you want, in my experience. I actually make it habit to go through any code that uses auto_ptr and change it to scoped_ptr, instead. If I get a compilation error, then it is generally meant to be shared_ptr.
Advertisement
Funny, every time I use std::auto_ptr, transfer of ownership is exactly what I want. Ex:
auto_ptr<Foo> get_foo(void);

This tells me that get_foo() returns a brand new Foo object just for me. On the other hand:
shared_ptr<Foo> get_foo(void);

doesn't have the same semantics. get_foo() could return a new Foo object, or it could return a reference to an already created Foo.

Admittedly, factory functions are pretty much the only place where I use auto_ptr.
Quote:Original post by SiCrane
Funny, every time I use std::auto_ptr, transfer of ownership is exactly what I want. Ex:
auto_ptr<Foo> get_foo(void);

This tells me that get_foo() returns a brand new Foo object just for me. On the other hand:
shared_ptr<Foo> get_foo(void);

doesn't have the same semantics. get_foo() could return a new Foo object, or it could return a reference to an already created Foo.

Admittedly, factory functions are pretty much the only place where I use auto_ptr.


Ahh, this is a difference in style. I use neither of those for factories. I return a raw pointer from the factory, since having the memory managed isn't useful at that point and therefore I'm imposing no restrictions on the caller for how they manage the memory, as to whether they want to use shared_ptr or scoped_ptr.
Quote:Original post by Rydinare
Quote:Original post by SiCrane
Funny, every time I use std::auto_ptr, transfer of ownership is exactly what I want. Ex:
auto_ptr<Foo> get_foo(void);

This tells me that get_foo() returns a brand new Foo object just for me. On the other hand:
shared_ptr<Foo> get_foo(void);

doesn't have the same semantics. get_foo() could return a new Foo object, or it could return a reference to an already created Foo.

Admittedly, factory functions are pretty much the only place where I use auto_ptr.


Ahh, this is a difference in style. I use neither of those for factories. I return a raw pointer from the factory, since having the memory managed isn't useful at that point and therefore I'm imposing no restrictions on the caller for how they manage the memory, as to whether they want to use shared_ptr or scoped_ptr.


But if you want to follow RAII then returning a classed resource is a lot more in keeping with that idoim. All those classed resources allow access to the underlying resource so you are not exactly limiting the client in anyway, slight overhead for robust code which is hardly a loss.

I'm just after reading some of Scott Meyers 55, and it mentioned lots of whats in this thread; just to highlight the worth to me :p, including the 'never place an implementation in std namespace, its not allowed and you will be punished :p', standard template 'complete' specialisations only.
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.
Quote:Original post by Guthur
Quote:Original post by Rydinare
Quote:Original post by SiCrane
Funny, every time I use std::auto_ptr, transfer of ownership is exactly what I want. Ex:
auto_ptr<Foo> get_foo(void);

This tells me that get_foo() returns a brand new Foo object just for me. On the other hand:
shared_ptr<Foo> get_foo(void);

doesn't have the same semantics. get_foo() could return a new Foo object, or it could return a reference to an already created Foo.

Admittedly, factory functions are pretty much the only place where I use auto_ptr.


Ahh, this is a difference in style. I use neither of those for factories. I return a raw pointer from the factory, since having the memory managed isn't useful at that point and therefore I'm imposing no restrictions on the caller for how they manage the memory, as to whether they want to use shared_ptr or scoped_ptr.


But if you want to follow RAII then returning a classed resource is a lot more in keeping with that idoim. All those classed resources allow access to the underlying resource so you are not exactly limiting the client in anyway, slight overhead for robust code which is hardly a loss.


I guess that's fair. My concern is that someone who isn't familiar enough with auto_ptr will think it can be used like a regular "smart" pointer, when it really has different semantics, and this will cause some difficult to find bugs. As to where, I think the factory pattern is well understood to return dynamic objects, so there's no surprises. If there was something better to return than auto_ptr<>, I'd feel a little better about this suggestion.
Quote:Original post by Rydinare
Ahh, this is a difference in style. I use neither of those for factories. I return a raw pointer from the factory, since having the memory managed isn't useful at that point and therefore I'm imposing no restrictions on the caller for how they manage the memory, as to whether they want to use shared_ptr or scoped_ptr.


Returning a auto_ptr doesn't stop the client from dumping it in whatever smart pointer they want. There's a shared_ptr constructor and scoped_ptr constructor just for sinking auto_ptrs. That is to say, these are perfectly legal:
  boost::shared_ptr<Foo> share_me(get_foo());  boost::scoped_ptr<Foo> dont_share_me(get_foo());


I know where you are coming from; I think I would have fallen into the trap of thinking auto_ptr<>'s copying functionality is a copy as oppose to a...well move:p.

But I think I may actually use the differing functionality at some point. I'm thinking it would be useful if you have a singleton like object that you want to share and access exclusively; thread safety may be be one area it has a use; I will qualify that by saying I have absolutely no experience of multithread programming :)
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.
Quote:Original post by SiCrane
Quote:Original post by Rydinare
Ahh, this is a difference in style. I use neither of those for factories. I return a raw pointer from the factory, since having the memory managed isn't useful at that point and therefore I'm imposing no restrictions on the caller for how they manage the memory, as to whether they want to use shared_ptr or scoped_ptr.


Returning a auto_ptr doesn't stop the client from dumping it in whatever smart pointer they want. There's a shared_ptr constructor and scoped_ptr constructor just for sinking auto_ptrs. That is to say, these are perfectly legal:
  boost::shared_ptr<Foo> share_me(get_foo());  boost::scoped_ptr<Foo> dont_share_me(get_foo());


*scratching chin* O I C. Hmmm. I hadn't realized they were there, because I generally have just avoided auto_ptrs. You have me rethinking that a bit... but I still have the concern that someone unfamiliar will make the mistake. I can speak from experience, because I used auto_ptrs incorrectly for a while when I first started using STL, many years ago. A lot of the time I got lucky and didn't get burned, but every once in a while I came across a bug that I couldn't solve and would wind up rewriting a portion of code until it worked. All because of the name auto, when you're new, you assume auto is short for "automatic", which makes you say, "Ah, sweet. They take care of everything!"

To rephrase, my concern is someone will do this:

    std::auto_ptr<Foo> share_me(get_foo());


But, I definitely see where you're coming from, and I may start using your technique, despite the newbie risk. I'll just have to make sure the junior programmers I work with are aware.
If the only reason you want an auto_ptr (or auto_array) is so you can create the object in a factory function and return it, wouldn't it be possible to make the auto_array non-copyable and use the release method to return the naked pointer? This should still follow RAII principles?

X* foo(){    auto_array<X> result(new X[n]);    //do some more stuff that might throw    //if it throws, result will be cleaned up    //...    //success    return result.release();}//store result in another auto_array if you so wish:    auto_array<X> some_x(foo());
Quote:But, I definitely see where you're coming from, and I may start using your technique, despite the newbie risk. I'll just have to make sure the junior programmers I work with are aware.

Well, it's not as if auto_ptr is a hidden corner of the standard library. Within arms reach right now I've got five C++ books (six if you count the standard). Four of them (The C++ Standard Library by Josuttis, Effective STL by Meyers, C++ Coding Standards by Sutter and Alexandrescu and C++ Gotchas by Dewhurst) contain warnings about auto_ptr. So statistically, I would expect any C++ programmer who's read two or more books on C++ to have some idea as to how auto_ptr works. I don't think that that would be considered an unreasonable expectation for a professional programmer or even a serious hobbiest using C++.

This topic is closed to new replies.

Advertisement