views:

747

answers:

8

What are the advantages and disadvantages of using auto pointers (auto_ptr), compared to ordinary pointers? I've heard it does automatic releasing of memory but how come it is not used often?

+5  A: 

Smart pointers are used often in C++, though perhaps not as often as they should be. The std::auto_ptr has a few problems (you can't use it in Standard Library collections, for example), but there are many others. The most popular of these are the ones that come with the Boost library, and which will be part of the next C++ standard - you should take a look.

Note that smart pointers are mostly about ownership, and deleting dynamically created objects. If you don't have dynamically created objects, you don't normally want smart pointers:

{
  int i = 42;
  auto_ptr <int> p( & i );   // bad!
}

You really don't want to do this, as when the autopointer goes out of scope, it will attempt to delete i. Unfortunately, i was not created dynamically, so bad things will happen. So you need both kinds of pointer, smart and normal, in most C++ programs.

anon
Yes, I've heard about those from Boost. It's just that my specific concern are the reasons why it is not used as often as ordinary pointers are used.
jasonline
`auto_ptr` isn't used very often because in most cases, the ones from Boost are preferable. Smart pointers *are* very often used, and at least among many programmers, more often than normal pointers. Why do you think normal pointers are more often used?
jalf
@ jasonline: In modern C++ code I hardly ever see normal pointers. Smart pointers are the norm and normal pointers are very much the exception. If you see any code that has pointers be very suspicious about the author. The only time I see normal (RAW) pointers is in demo code are tutorials for teaching students what pointers are.
Martin York
jasonline
@Martin York: Thanks, I understand that smart pointers are much preferred.
jasonline
auto pointers have one major problem: They can not be used in standard library containers. Their transfer-of-ownership semantics can't really be expressed robustly in C++ as the language stands today, and `auto_ptr` was a compromise trying to approximate something like it, but with some major pitfalls too. So in practice, it's not very widely used, especially as Boost's collection of smart pointers have taken over. C++0x adds `unique_ptr` which is basically `auto_ptr` done *right*. Of course, the reason it works there is that it relies on rvalue references, a feature added in C++0x.
jalf
@jalf Perhaps that is an answer, rather than a comment?
anon
@Neil: It is. @raymond-holmboe and @abhay already mentioned it in their answers. ;)
jalf
A: 

The auto_ptr has an ownership model for the object it points at. You cannot have multiple refrences to the same object, and you cannot put them in stl containers and such - code that looks like it does that is actually transferring ownership, and going to cause nasty difficult-to-track-down bugs in production.

boost's shared_ptr is in almost all cases much more practical.

Will
You should be careful with Boost smartpointers too :)
n0rd
If used correctly why would it cause hard to track down problems. std::auto_ptr does exactly what it was intended to do (no more no less). std::tr1::shared_ptr is a completely different type of smart pointer. learn to use the correct type of smart pointer.
Martin York
I expect you never have a bug, ever, Martin :)
Will
+7  A: 

The main drawback of std::auto_ptr is that it has the transfer-of-ownership semantic. That makes it impossible to store std::auto_ptr in STL containers because the containers use the copy constructor when you store or get an element.

Also, another important aspect that i have noticed about the std::auto_ptr is that they cannot serve in the use of PIMPL idiom. This is because, they require the complete definition of the wrapped class's destructor. See this thread on c.l.c++.m for more detailed discussion.

Update: Transfer of ownership

class Test {};
std::auto_ptr<Test> ap_test_1(new Test);
std::auto_ptr<Test> ap_test_2(new Test);

ap_test_2 = ap_test_1;  // here ap_test_1's ownership is transferred i.e. ap_test_2 is the 
                        // new owner and ap_test_1 is NULL.

See this thread on Herb Sutter's site for more details on what this means when used in a STL container used by STL algorithms.

Abhay
Yes, I think this would answer my question but can you explain more about this transfer-of-ownership?
jasonline
auto_ptr *can* be used for pimpl; it's just not particularly nice because you must declare and implement a destructor. Better to use a boost::scoped_ptr (or shared_ptr) which doesn't require the dtor definition.
MattyT
I have no problem using std::auto_ptr for PIMPL.
Martin York
@Martin: Then you need to provide complete definition of the class that u r wrapping. The main purpose of PIMPL in many projects is to implement a compiler firewall/hide the implementation. In such a case you cannot include a header for the class, it has to work just on a forward declaration. This is not possible with std::auto_ptr, see the c.l.c++.m thread for a detailed discussion.
Abhay
@MattyT: i think boost::scoped_ptr also requires the definition of class dtor. Since boost::shared_ptr allows for a custom deleter, it does not require.
Abhay
I disagree. The implementation is usually a concrete representation of an abstract class. You only need the abstract definition.
Martin York
@Martin: Strictly speaking the CheshireCat as it was called earlier (now PIMPL), showcases pointer usage only using a class forward declaration. Ofcourse you can create an abstract interface for the implementation but it will increase one level of indirection. Consider the classic case of hiding the GUI layer in applications. You will need to moc the entire interface of the concrete class! So i think using abstractions to me seems more to circumvent the dtor definition problem. Else in the classic sense, PIMPL is based on just a forward declaration.
Abhay
@Abhay You're right; Although scoped_ptr's are allowed to be *declared* with incomplete types, when any operations are called (like the dtor) the complete type must be available. So the dtor has to be declared in the header but, unlike auto_ptr, the dtor implementation can be out-of-line (in the .cpp).So yeah, use shared_ptr. :)
MattyT
@Martin You're correct that all works well when the auto_ptr contains an abstract class (assuming a virtual dtor). I disagree that this is "usually" the case. In my experience it's the exception rather than the rule.
MattyT
A: 

Don't confuse auto pointers (std::auto_ptr) with the family of smart pointers (notably std::auto_ptr, boost::scoped_ptr and boost::shared_ptr).

I pretty much never use auto pointers because, most of the time, i'd rather use references. The only time when i do is for member variables that can't be instantiated in the constructor of the object.

On the contrary, smart pointers are very powerful, but that's not your question, i guess :)

Benoît
A: 

The advantages is that for simple use, they do their job.

void foo() {
  std::auto_ptr<int> bar(new int);
  // do the stuff that potentially throw

} // the auto_ptr destructor will call delete here 

The disadvantage is that as soon as you escape from this simple use, you hit the bad semantics of auto_ptr.

std::auto_ptr<int> foo(new int);
std::auto_ptr<int> bar = foo;    // foo is changed here! It does not have ownership anymore.

You'd better use unique_ptr and shared_ptr that have good semantics, and that are available in boost::, and will be available in std:: in the next C++ standard

Didier Trosset
A: 

The short story: std::auto_ptr can't be shared, regular pointers can.

And then there's Boost.SmartPointer

larsm
+1  A: 

Maybe the biggest reason on why it's not widely used:

The std::auto_ptr has a tremendous disadvantage: It can not be copied without destruction. When you need to make a copy of an auto pointer, the original instance is destroyed. This means you may only have a single copy of the object at any time. This also means that auto_ptr can not be used with standard containers, such as vector, deque, list, set, and map. In fact, it can hardly be used in any class that relies on copy construction.

Furthermore, auto_ptr is not safe, because nothing prevents you from doing a copy accidentally. And if you do so, you destroy the original copy. Also, some less standard compliant C++ compilers let you store forward declared objects in an auto_ptr, and use that without ever including the full definition of the class. This always results in a memory leak.

+1  A: 

The main raison d'être for auto_ptr is to transfer ownership in an exception safe manner. Although most people use it as a poor man's boost::scoped_ptr.

The primary usage is for functions returning using objects pointers as parameters or return values.

For example a factory function

std::auto_ptr<MyClass> createMyClass(MyClass::Type type) {
    if (type == MyClass::TypeOne) {
        return std::auto_ptr(new MyClassOne);
    }
    else {
        return std::auto_ptr(new MyClassTwo);
   }
}


void foo() {
    std::auto_ptr<MyClass> myc = createMyClass(MyClass::TypeOne);

    // use myc
}

While this code is very simple and no exceptions should be thrown if exceptions are thrown myc handles it correctly, where doing this with raw pointers would be hard.

boost::shared_ptr can be used also, but this provides more functionality than required it also indicates that you expect the object to be shared. Where with auto_ptr is simpler and you're are clearly stating that you are transferring ownership.

I was recently told about boost::unique_ptr which seem to have the same usage as auto_ptr without the drawbacks.

see http://stackoverflow.com/questions/974964/best-practice-when-returning-smart-pointers/ for more info

iain