Redeeming qualities of auto_ptr?

Started by
30 comments, last by Emmanuel Deloget 17 years, 1 month ago
As we all like to think, auto_ptr == evil because of the ownership-transfer for every assign:

auto_ptr<Foo> p1(new Foo);
auto_ptr<Foo> p2(p1); // Oh snap, p1 is now NULL!!
This is so reeking with evilness that the standards committee has made it part of the c++ standard that you should not be allowed to make STL containers of auto_ptrs (since many algorithms will cause elements in containers to be copied, and stuff will break as a result). The question: Does auto_ptr have ANY redeeming properties, that would excuse it and make it worthy of being in the standard still? Once std::tr1 goes out, and all the "boost::*_ptr" stuff ends up being part of it, will there be ANY reason at all to ever use auto_ptr? Will it stay in the standard for any reason other than backwards compatibility?
Advertisement
Its useful for functions that create an object and return a pointer to it, like factories (but I usually have these return shared_ptrs anyway). It can be used for simple scoped objects created with new() that you don't want to stack allocate for some reason, say if the object was very large ( I think boost also has a scoped_ptr, but I've never realy looked at it ).

But that said I tend to default to boost::shared_ptr for pretty much everything. I did a quick search in my current project and found a single auto_ptr, and that is a temporary thing I'm using while I test something.
I think Sutter has some good points on its better qualities.

I dont know if all boost ptr classes will be included, but unless I have boost all i use auto_ptr for is as a replacement for scoped_ptr. It can be a good hint to use auto_ptr when you want to point out that you are passing ownership, but I seldom do that :/
Quote:Original post by Replicon
As we all like to think, auto_ptr == evil because of the ownership-transfer for every assign:

auto_ptr<Foo> p1(new Foo);auto_ptr<Foo> p2(p1); // Oh snap, p1 is now NULL!!


This is so reeking with evilness that the standards committee has made it part of the c++ standard that you should not be allowed to make STL containers of auto_ptrs (since many algorithms will cause elements in containers to be copied, and stuff will break as a result).

The fact that auto_ptrs don't work with STL containers is a consequence of the lack of a const copy constructor combined with STL semantics, not an explicit design decision in its own right. If you wrote a smart pointer that worked like auto_ptr, and wrote a container that worked like std::vector, the two would automatically not work together.

And calling it "evil" is a bit of an overreaction. It's strange, yes. But since the auto_ptr copy constructor takes a non-const reference, there's no chance of it stomping all over structures you didn't expect it to stomp all over in properly const-correct code (your code IS const-correct, right?), and the worst case is simply a pointer you didn't expect to be NULL. Hardly the most oblique or difficult-to-troubleshoot part of C++.
Quote:Original post by SneftelAnd calling it "evil" is a bit of an overreaction. It's strange, yes.


That's very true, and I admit to wanting to make it look more dramatic than it really is. I'd call it 'dangerous' before 'strange' though, and depending on where the issue is encountered, it can yield behaviour that is very... misdirecting? But is explicitely defining who has ownership really that important? I've always felt it was like an unnecessary chore where the possible pitfalls far outweigh the benefits. Is there, for instance, a huge performance penalty incured from using a reference counted pointer (e.g. shared_ptr) in places where a basic auto_ptr type thing would have worked fine?
Fortunately, C++0x will allow us to replace auto_ptr with the goodness that is unique_ptr.
Quote:
The question: Does auto_ptr have ANY redeeming properties, that would excuse it and make it worthy of being in the standard still? Once std::tr1 goes out, and all the "boost::*_ptr" stuff ends up being part of it, will there be ANY reason at all to ever use auto_ptr? Will it stay in the standard for any reason other than backwards compatibility?

Yes. It implements transfer of sole-ownership semantics, which none of the boost ptrs offer.

There's nothing dangerous about auto_ptr unless you fundamentally misunderstand
it's purpose - as smart pointer that can transfer ownership.

I could equally argue that boost::weak_ptr is dangerous because it can change from a valid pointer to a null pointer - or I could understand the semantics of the class I'm using.


The unique_ptr example linked is very silly indeed. It 'solves' the 'problem' with auto_ptr by removing the transfer of ownership semantics. If that replaces auto_ptr in the standard, then anyone wishing to return a dynamically allocated resource from a function will need to to use their own implementation of auto_ptr (or use a shared_ptr - which introduces its own 'dangers').

Quote:
From the linked paper:
You can safely put unique_ptr into containers. If the containers move elements around internally instead of copy them around (as proposed for the standard containers), unique_ptr will work without problems. If the container does use copy semantics for its value_type, then the client will be notified immediately (at compile time). There is no chance of a run time error due to a move being mistaken for a copy.


Oh dear. Someone should tell the author that std::auto_ptrs currently cause std container to fail at compile time, and that whatever move semantics end up in C++0x will allow containers to be implemented in a way compatible with auto_ptr.

unique_ptr does add useful functionality - the custom delete (a la shared_ptr), but it really needs to retain its transfer of ownership semantics.
I find auto_ptr extremly useful in class constructors for pointing out that the class now owns that pointer instead of making an internally owned copy, for example if i had a tecture class that took a pointer to the data in a certain format i would have to constructors one which took an ordinary pointer to the data and made an internal copy and one which took an auto_ptr and canabalized the given data and memory for its own use.
Quote:Original post by Replicon
I'd call it 'dangerous' before 'strange' though, and depending on where the issue is encountered, it can yield behaviour that is very... misdirecting?

I wouldn't call it dangerous. Dangerous is something that works 98% of the time, or 100% on your particular computer and 50% on other people's, etc. Something that never works is easy to detect, and something that's easy to detect is easy to fix.

As for misdirecting.... maybe. I've never been surprised by auto_ptr, but that's because I know and can expect how it works. Alongside scoped_ptr, I only end up using it in special situations where I want exactly that behavior.

Quote:But is explicitely defining who has ownership really that important?

Well, no. Not anymore. I use shared/weak ptr for virtually everything now (including Ogre objects; ask me how!) and that makes lifetime management very easy. In really tight loops you should definitely avoid weak_ptr and probably shared_ptr, but in those circumstances you're peering at the code closely enough that there's little ease-of-use to be gained from auto_ptr over raw pointers. The big remaining advantage is exception safety, but you won't need that in a tight loop.

I will say, though, that when working with a team which is unwilling for historical reasons to embrace smart pointers, auto_ptr can go a long way towards maintaining sanity.
Quote:Original post by Sharlin
Fortunately, C++0x will allow us to replace auto_ptr with the goodness that is unique_ptr.

Not to mention that tr1::shared_ptr<> will be imported back into the std namespace - so we'll have std::shared_ptr, std::weak_ptr and std::enable_shared_from_this.

Regarding auto_ptr<>, I don't look iit as an evil class. It has its use - if you don't need the can-share semantics of shared_ptr, auto_ptr workds just fine. I use it quite extensively for objects that need to be allocated. I find it weird - because of its semantics - but once you get those right, it's still a useful tool.

Regards,

This topic is closed to new replies.

Advertisement