auto_ptr
uses a dirty trick.
I'll use a dumbed-down class named auto_int
to demonstrate just the copy construction functionality without bringing in any complexities introduced by templates or inheritance. I think the code is mostly correct, but it's untested. Our basic auto_int
look something like this:
class auto_int
{
public:
auto_int(int* p = 0) : p_(p) { }
~auto_int() { delete p_; }
// copy constructor taking a non-const reference:
auto_int(auto_int& other)
: p_(other.release()) { }
int* release()
{
int* temp = p_;
p_ = 0;
return temp;
}
private:
int* p_;
};
With this basic auto_int
, we can't copy a temporary object. Our goal is to be able to write something like:
auto_int p(auto_int(new int()));
What we can do is use a helper class. For auto_ptr
, this is called auto_ptr_ref
. We'll call ours auto_int_ref
:
class auto_int;
class auto_int_ref
{
public:
auto_int_ref(auto_int* p) : p_(p) { }
auto_int& ref() { return *p_; }
private:
auto_int* p_;
};
Basically, an instance of this class just stores a pointer to an auto_int
and allows us to use it as a "reference" to an auto_int
.
Then in our auto_int
class we need two additional functions. We need another constructor that takes an auto_int_ref
and we need a conversion operator that allows an auto_int
to be implicitly converted to an auto_int_ref
:
auto_int(auto_int_ref other)
: p_(other.ref().release()) { }
operator auto_int_ref() { return this; }
This will allow us to "copy" a temporary while still having the copy constructor take a non-const reference. If we look again at our sample code:
auto_int p(auto_int(new int()));
What happens is we construct a new temporary auto_int
and pass new int()
to the constructor that takes an int*
. This temporary is then converted to an auto_int_ref
that points to it, using the operator auto_int_ref()
, and the auto_int
constructor that takes an auto_int_ref
is used to initialize p
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…