020_拷贝构造函数的四种调用时机

/*
    copy构造函数的调用  时机1 时机2
*/

#if 1
class Test4
{
public:
    Test4()  //无参数构造函数
    {
        m_a = 0;
        m_b = 0;
        cout << "我是构造函数,自动被调用了" << endl;
    }

    Test4(int a)
    {
        m_a = a;
        m_b = 0;
    }

    Test4(int a, int b) //有参数构造函数   //3种方法
    {
        m_a = a;
        m_b = b;
        cout << "有参数构造函数" << endl;
    }

    //赋值构造函数 (copy构造函数)  作用完成对象的初始化
    Test4(const Test4& obj)
    {
        cout << "我也是构造函数,我是通过另一个对象obj来初始化我自己 " << endl;
        m_a = obj.m_a + 100;
        m_b = obj.m_b + 100;
    }


    ~Test4()
    {
        cout << "我是析构函数,自动被调用了" << endl;
    }

public:
    void printT()
    {
        cout << "普通成员函数" << endl;
        cout << "m_a = " << m_a << ", m_b = " << m_b << endl;
    }

private:
    int m_a;
    int m_b;

};

void test()
{
    //赋值构造函数 用一个对象初始化另一个对象
    Test4 t1(10, 12);
    Test4 t0(0, 2);

    //赋值操作 和 初始化是两个不同的概念

    //赋值 = 操作  不会调用拷贝构造函数,编译器给我们提供的浅copy
    t0 = t1;        //用t1 给 t0赋值    

    //第一种 调用拷贝构造函数的时机
    Test4 t2 = t1;  //用t1来初始化t2,调用t2这个对象的拷贝构造函数
    t2.printT();

    //第二种 调用拷贝构造函数的时机
    Test4 t3(t1);   //用t1来初始化t2
    t3.printT();
}

#endif

这里写图片描述

/*
    赋值构造函数的调用  时机3
    */
#if 1
class Location
{
public:
    //构造函数
    Location(int xx = 0, int yy = 0)
    {
        X = xx;
        Y = yy;
        cout << "Constructor Object." << endl;
    }
    //拷贝构造函数  完成对象的初始化
    Location(const Location &obj)
    {
        X = obj.X;
        Y = obj.Y;
        cout << "copy 构造函数." << endl;
    }

    ~Location()
    {
        cout << X << "," << Y << " Object destroyed." << endl;

    }
    int GetX()
    {
        return X;
    }
    int GetY()
    {
        return Y;
    }
private:
    int X, Y;
};

//第三种 调用拷贝构造函数的时机
void f(Location p)  //参数是一个元素
{
    cout << p.GetX() << endl;
}

void test()
{
    Location a(1, 2);
    Location b = a;     //第一种 调用拷贝构造函数的时机
    /*
        实参b去初始化形参p,c++编译器会调用形参 p 这个对象的copy构造函数,
        由于p是局部变量,函数f()运行完毕,p对象的生命周期结束,会调用
        p对象的析构函数。

        先创建的对象后释放
    */
    //b实参去初始化形参p,会调用copy构造函数 
    cout << "-------1------" << endl;
    f(b);           //第3种时机
    cout << "-------2------" << endl;
    cout << "b对象已经初始化完毕" << endl;

}
#endif

这里写图片描述

/*
    赋值构造函数的调用  时机4
*/
#if 1
class Location
{
public:
    //构造函数
    Location(int xx = 0, int yy = 0)
    {
        X = xx;
        Y = yy;
        cout << "Constructor Object." << endl;
    }
    //拷贝构造函数  完成对象的初始化
    Location(const Location &obj)
    {
        X = obj.X;
        Y = obj.Y;
        cout << "copy Constructor Object." << endl;
    }

    ~Location()
    {
        cout << X << "," << Y << " Object destroyed." << endl;

    }
    int  GetX() { return X; }       int GetY() { return Y; }
private:
    int X, Y;
};

//第4种 调用拷贝构造函数的时机
Location g()
{
    Location A(11, 22);//执行对象A的构造函数
    return A;
    /*
    return A;
    这条语句  首先会创建一个匿名对象,用对象A初始化匿名对象,执行匿名对象的copy构造函数,
    然后对象A的生命周期结束了,会执行对象A的析构函数。g()返回一个匿名对象.
    */
}

//测试匿名对象的生命周期
void objplay2()
{
    g();//g()返回一个匿名对象,如果匿名对象没人接,则会执行匿名对象的析构函数。
}


运行结果(测试匿名对象的生命周期)
这里写图片描述

/*
g()函数 返回一个元素
结论 1:函数的返回值是一个元素(复杂类型的),返回一个新的匿名对象(所以会调用匿名对象
的 copy构造函数)。
结论 2:有关匿名对象的去和留
如果用匿名对象 初始化 另一个同类型的对象,匿名对象转化为有名对象,匿名对象不会被析构掉
如果用匿名对象 赋值给 另一个同类型的对象,匿名对象被析构
*/

void objplay3()
{
    //用匿名对象初始化m,此时c++编译器直接把匿名对象转成m(扶正),从匿名转成有名对象了m
    Location m = g();
    printf("匿名对象,被扶正,不会被析构掉\n");
    cout << m.GetX() << endl;
}

运行结果(函数返回的匿名对象的去初始化另一个对象)
这里写图片描述

void objplay4()
{
    Location m2(1, 2);
    m2 = g();//用匿名对象 赋值给 m2
    printf("因为用 匿名对象 赋值 给m2, 匿名对象被析构\n");
    cout << m2.GetX() << endl;
}

运行结果(函数返回的匿名对象的去赋值另一个对象)
这里写图片描述

void objplay5()
{
    //用匿名对象 赋值给 m2
    Location m1(1, 2);
    cout << "------1-----" << endl;
    m1 = Location(33, 44);  //赋值操作   Location(33, 44)会产生匿名对象,匿名对象被析构
    cout << "------2-----" << endl;
    Location m2 = Location(55, 66);//初始化操作 Location(55, 66)会产生匿名对象,匿名对象转正,不会被析构
    cout << "------3-----" << endl;
}

运行结果:
这里写图片描述

void objplay6()
{
    Location(77, 88);  //直接调用构造函数,会产生匿名对象,临时匿名对象的生命周期  
    cout << "------1-----" << endl;
}

这里写图片描述

void test()
{
    //objplay2();
    //objplay3();
    //objplay4();
    //objplay5();
    objplay6();

}
#endif

猜你喜欢

转载自blog.csdn.net/WUZHU2017/article/details/82625723