explicit、复制构造函数 和 复制函数

本文的目的是为摸清类类型转换、对象初始化期间到底发生了什么

设计了3段代码:


class CLASS_TYPE{
public:
    int a;
    CLASS_TYPE(int dd) : a(dd)
    {
        print("fun A ");
    }
    CLASS_TYPE(const CLASS_TYPE & bb)
    {
        a = bb.a;
        print("fun B ");
    }
    CLASS_TYPE & operator=(const CLASS_TYPE & rhs)
    {
        a = rhs.a;
        print("fun C");
    }
};


class CLASS_TYPE{
public:
    int a;
    CLASS_TYPE(int dd) : a(dd)
    {
        print("fun A ");
    }
    explicit CLASS_TYPE(const CLASS_TYPE & bb)
    {
        a = bb.a;
        print("fun B ");
    }
    CLASS_TYPE & operator=(const CLASS_TYPE & rhs)
    {
        a = rhs.a;
        print("fun C ");
    }
};


class CLASS_TYPE{
public:
    int a;
    explicit CLASS_TYPE(int dd) : a(dd)
    {
        print("fun A ");
    }
    CLASS_TYPE(const CLASS_TYPE & bb)
    {
        a = bb.a;
        print("fun B ");
    }
    CLASS_TYPE & operator=(const CLASS_TYPE & rhs)
    {
        a = rhs.a;
        print("fun C ");
    }
};

然后对这3中类定义执行两种复制初始化(一种是从已定义的对象复制初始化,一种是从整形复制初始化),再执行两种复制操作。

结果如下表:

na 语句
场景1 CLASS_TYPE objb = obja; fun B 编译错误 fun B
场景2 CLASS_TYPE objb = 33; fun A 编译错误 编译错误
场景3 objb = obja; fun C fun C fun C
场景4 objb = 33; fun A fun C fun A fun C 编译错误


大致结论:

场景3,没什么好说的,直接调用“=”复制操作符


场景4,是在复制时发生类型转换的场景。①的结果表明,先调用了输入参数为int的构造函数,然后调用了复制操作符。因为int参数的构造函数是隐式调用的,所以在③里,这个函数加了explicit后,就不灵光了


场景2,是使用int进行复制初始化的场景。从①的结果看,似乎被转化成了对CLASS_TYPE(int dd)的调用,而和CLASS_TYPE(const CLASS_TYPE & bb)无关,但若和CLASS_TYPE(const CLASS_TYPE & bb)真的一点关系都没有,那②就不应该报错。结合②、③来看,场景2应该是先调用CLASS_TYPE(int dd)生成临时对象tmpobj,然后以tmpobj为参数调用CLASS_TYPE(const CLASS_TYPE & bb)初始化objb。但是为什么运行结果只打印出了fun A呢?估计是生成代码时编译器对这个流程作了优化,把先fun A再fun B的流程优化成了直接调用CLASS_TYPE(int dd)来初始化objb,这样避免了生成临时对象。虽然结果有优化,但编译检查仍然是按照先fun A再fun B的流程来检查的。②、③中分别给funB和funA加了explicit关键字,使得它们不能隐式调用,所以就编译错误了。


场景1,毫无疑问的是,这个场景只调用CLASS_TYPE(const CLASS_TYPE & bb)。但问题是,编译阶段会check几次。很有可能是和场景2一样的原理,但说不准也有可能只check1次。但这已经无关紧要了。

你可能感兴趣的:(explicit、复制构造函数 和 复制函数)