It is rather confusing. Basically, auto_ptr_ref
exists because the auto_ptr
copy constructor isn't really a copy constructor in the standard sense of the word.
Copy constructors typically have a signature that looks like this:
X(const X &b);
The auto_ptr
copy constructor as a signature that looks like this:
X(X &b)
This is because auto_ptr
needs to modify the object being copied from in order to set its pointer to 0 to facilitate the ownership semantics of auto_ptr
.
Sometimes, temporaries cannot match a copy constructor that doesn't declare its argument const
. This is where auto_ptr_ref
comes in. The compiler won't be able to call the non-const version of the copy constructor, but it can call the conversion operator. The conversion operator creates an auto_ptr_ref
object that's just sort of a temporary holder for the pointer. The auto_ptr
constructor or operator =
is called with the auto_ptr_ref
argument.
If you notice, the conversion operator in auto_ptr
that automatically converts to an auto_ptr_ref
does a release
on the source auto_ptr
, just like the copy constructor does.
It's kind of a weird little dance that happens behind the scenes because auto_ptr
modifies the thing being copied from.
Random related tanget about C++0x and unique_ptr
In C++0x, auto_ptr
is deprecated in favor of unique_ptr
. unique_ptr
doesn't even have a copy constructor and uses the new 'move constructor' which is explicit about the fact that it will modify the object being moved from and leave it in a useless (but still valid) state. Temporaries (aka rvalues) are explicitly always allowed to be arguments to a move constructor.
The move constructor in C++0x has a number of other big benefits. It enables the standard STL containers to store unique_ptr
s and do the right thing, as opposed to how auto_ptr
s cannot be. It also mostly eliminates the need for the 'swap' function as the whole purpose of the swap function is usually to be a move constructor or move assignment operator that never throws.
Which is the other expectation. The move constructor and move assignment operator (much like a destructor) are never supposed to throw.