int *p = new int;
auto_ptr<int> ap1 = p; //will fail on 3 1
auto_ptr<int> ap1(p); //ok 2
*ap1 = 12; // 3
the first situation has called : explicit auto_ptr(_Ty *_Ptr = 0)
_THROW0()
According to the standard, the line labeled 1 first converts the
argument to the target type, then copies. Since the one
argument constructor is marked explicit, it can't be used for
conversion; in fact, there is no implict conversion, and line
one should fail to compile. (G++ says: "error: conversion from
'int*' to non-scalar type 'std::auto_ptr<int>' requested")
Many of the earlier versions of auto_ptr allowed it, so if you
have an older compler, it might compile; some newer ones might
allow it as well, to avoid breaking older code.
the second : auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
Nothing in your code should call this. The line labeled 2 calls
st::auto_ptr<int>( int* ), exactly as it looks like. In this
case, no conversion is involved, so the "explicit" doesn't
inhibit anything.
why the two expression have called the different ctor?
Because they have different semantics. The statement labeled 1
is "copy initialization", and the statement labeled 2 is "direct
initialization". Although the exact details are a bit more
complex, the basic principle is that copy initialization
converts the initialization to the target type, then uses the
copy constructor to copy it. (The additional temporary, and
thus the copy constructor, may be elided, but the legality of
the code may not depend on this elision.) Direct initialization
does exactly what it's name says, it calls the constructor for
the object with the given arguments.
is the 1 expression has compiled as follow?
auto_ptr<int> ap1;
ap1 = p;
Never. Despite the =, copy initialization is *not* assignment,
and does not involve assignment. (Of course, this won't compile
with auto_ptr either, since there is no assignment operator
which takes a pointer. But in earlier versions, there was, so
your milage may vary.)