ali_bahoo
ali_bahoo

Reputation: 4863

Why does assignment operator call constructor?

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?

Upvotes: 13

Views: 4015

Answers (4)

Loki Astari
Loki Astari

Reputation: 264381

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. 

Upvotes: 2

casablanca
casablanca

Reputation: 70701

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.

Upvotes: 6

engf-010
engf-010

Reputation: 3929

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.

Upvotes: 0

Karl Knechtel
Karl Knechtel

Reputation: 61509

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.

Upvotes: 16

Related Questions