问题
I am just playing around to understand smart pointers and trying to make mine but I come across a situation that I do not fully understand. Here is the code:
#include <iostream>
template <class T>
class Holder
{
private:
T * obj;
public:
Holder(T * tt) : obj(tt)
{
std::cout << "ctor : " << tt->dummy << std::endl;
}
T * operator -> ()
{
return obj;
}
operator bool()
{
return obj;
}
T * const get() const
{
return obj;
}
void reset() {swap(0);}
void swap(T * other)
{
obj = other;
}
Holder & operator = (const Holder& holder)
{
obj = holder.get();
return *this;
}
Holder(const Holder & holder) : obj(holder.get()) {}
};
class A
{
public:
int dummy;
A(int a) : dummy(a) {}
};
int main ()
{
A * a = new A(1);
Holder<A> holder(a);
A * b = new A(2);
holder = b;
std::cout << holder->dummy << std::endl;
return 0;
}
The code compiles and on the line of holder = b;
the constructor of Holder
class is called. I thought compiler would give an error. It is not the assingment operator but why is it calling constructor?
回答1:
holder = b
attempts to assign from b
to Holder
. b
is of type A*
, and holder
is of type Holder<A>
.
The Holder
template defines assignment from another instance of the same Holder
type, so the compiler looks for a conversion from A*
to Holder<A>
. It finds the constructor, and uses that.
Constructors which may take exactly one argument may be used for implicit conversions, unless you tag them with the explicit
keyword.
回答2:
Both the constructor and assignment operator are called. You can check this by printing something in operator =
.
This happens because operator =
is defined to take a const Holder &
, but b
is of type A *
. So first the Holder(T *)
constructor is called to create a temporary object, then this object is assigned to holder
through operator =
.
If you define an operator =(const T *)
, only the assignment operator will be called.
回答3:
I do not see a version of the assignment operator that takes a right hand side of A*
A* a = new A(1);
Holder<A> holder(a);
A* b = new A(2);
// assigning object of type A* to Holder<A>
holder = b;
// No appropriate assignment operator provide.
// But a constructor is available to convert RHS parameter to correct type.
// So compiler generates the following code:
holder = Holder<A>(b);
// There is an appropriate assignment operator for this.
// So it compiles.
回答4:
You have a constructor taking a T* . Your assigment has a rhs pointer ,so it construct a temp-obj with that pointer as argument and assigns this to holder.
来源:https://stackoverflow.com/questions/4383015/why-does-assignment-operator-call-constructor