为什么赋值运算符会调用构造函数?

12

我只是在玩弄智能指针并尝试制作自己的智能指针,但我遇到了一个我没有完全理解的情况。下面是代码:

#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;
} 

代码编译,并在holder = b;行调用了Holder类的构造函数。我以为编译器会报错。这不是赋值操作符,为什么它会调用构造函数?

Holder 有两个构造函数,哪一个会被调用? - suszterpatt
4个回答

16

holder = b 尝试将 b 的值赋给 Holder。其中,b 的类型为 A*,而 holder 的类型是 Holder<A>

Holder 模板定义了从同一类型的另一个实例进行赋值的方法,因此编译器会查找如何将 A* 转化为 Holder<A>。它找到构造函数并使用它完成转换。

当构造函数只接收一个参数时,可以用于隐式转换,除非你在声明时使用了 explicit 关键字。


6
构造函数和赋值运算符都被调用。您可以通过在operator =中打印一些内容来检查这一点。
这是因为operator =被定义为接受一个const Holder &,但b的类型为A *。因此,首先调用Holder(T *)构造函数创建临时对象,然后通过operator =将该对象分配给holder
如果定义了operator =(const T *),则只会调用赋值运算符。

2

我没有看到一个以 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. 

0

你有一个接受 T* 的构造函数。 你的赋值操作有一个 rhs 指针,所以它使用该指针构造一个临时对象,并将其分配给 holder。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接