Ownership of objects pointed to by auto_ptr is transferable, but not shareable. This means that only one auto_ptr can be used to point to some object at any time. You point another auto_ptr to the same object and the old auto_ptr is automatically null-ed.
Particularly, with
void function1(std::auto_ptr<Base> base) {}
you are actually stating that the object passed to function1 should be deleted before the function returns.
There are two or three circumstances where auto_ptr is useful.
1. In the constructor of your class/struct:
1 2 3 4
|
struct A {
auto_ptr<T> ptr;
A() : ptr(new T()) { /*do whatever that may cause exception*/ }
}
|
This guarantees that if the exception is triggered in the constructor body, the object pointed by ptr will be deallocated. It also ensures that the object pointed by ptr is automatically deallocated in the destructor without extra code.
2. In function
1 2 3 4 5
|
void g(T*);
void f() {
auto_ptr<T> ptr = new T();
g(ptr.get());
}
|
This guarantees that if the function g throws exception, then the object pointed to by ptr will be deleted. Basically, protects against "multi-level returns". Also, it saves you the hassle of doing the deallocation manually in the end of the function, although you can always opt to do it earlier.
3. As return value from function (less useful though)
1 2 3 4 5
|
auto_ptr<T> f() {
auto_ptr<T> ptr = new T();
...
return ptr;
}
|
Objects pointed to by boost::shared_ptr can be .. you know, shared.
Regards
EDIT:
Now I see that I actually didn't answer your questions fully.
Regarding the conversion ambiguity that you get from your compiler. The following code will work with gcc:
1 2 3 4 5 6 7 8 9 10
|
class Base {};
class Derived : public Base {};
void function1(auto_ptr<Base> base) {}
int main()
{
auto_ptr<Derived> test(new Derived());
function1(static_cast< auto_ptr<Base> >(test));
}
|
The first obvious problem is that the inheritance in class-es (vs struct-s) is by default private and there is no implicit conversion sequence from Derived* to Base* in such case. Which is why it is necessary to specify the inheritance as public manually as I've done above. The second issue is that the auto_ptr template class has conversion operators and conversion constructors between all auto_ptr template instances. The operator and constructor conversions rank the same in this case, i.e. the conversion is ambiguous.
What I cannot understand is why the use of static_cast (and function style cast and c-style cast) fixed the problem. Aren't they supposed to issue the same conversions in this case? I found out (using code traces) that the preferred method ends up being the templated auto_ptr constructor. Why?
As to why you shouldn't use auto_ptr in standard containers - because they expect that all copies of the objects they store (be pointers or not) to be effectively equivalent. A copy of an auto_ptr removes ownership from the original (and zeroes it), therefore violating this assumption.