C++对象的复制与赋值,以及以对象作为函数的参数和以对象作为函数的返回值

这是我对“C++对象的复制与赋值,以及以对象作为函数的参数和以对象作为函数的返回值”的理解,若有不对之处还望业内同仁指正,在下感激不尽!下面用代码论述之:

#include<iostream>
using namespace std;

class Dog
{
public:
    Dog(){cout << "调用了无参构造函数" << endl;}
    Dog(int age)
    {
        this->m_nAge = age;
        cout << "调用了有参构造函数" << endl;
    }
    Dog(const Dog& d)//拷贝构造函数
    {
        this->m_nAge = d.m_nAge;
        cout << "调用了拷贝构造函数" << endl;
    }
    ~Dog(){ cout << "析构函数被调用" << endl; }
    friend ostream& operator<<(ostream& out, Dog& d)
    {
        out << "年龄:" << d.m_nAge;
        return out;
    }
    void act(){ cout << "狗" << endl; }
public:
    int m_nAge;
};

Dog test(Dog d)
{
    return d;
}

Dog test1()
{
    Dog d;//一个局部对象
    printf("局部对象d的地址为:%p\n",&d);
    return d;
}

Dog& test2(Dog& d)
{
    printf("d的地址为:%p\n", &d);
    return d;
}

void main()
{
    //一、对象的复制
    /*Dog d1(1);
    Dog d2 = d1;//对象的复制,将调用拷贝构造函数
    Dog d3(d2);//对象的复制,将调用拷贝构造函数
    printf("d1的地址:%p\nd2的地址:%p\nd3的地址:%p\n",&d1,&d2,&d3);
    cout << d1<<endl;
    cout << d2 << endl;
    cout << d3 << endl;*/

    //二、对象的赋值
    /*Dog d4(123), d5(456);//定义了两个对象,未赋值的成员将具有不可预见的值
    cout << d4 << endl;
    cout << d5 << endl;
    printf("d4的地址:%p\nd5的地址:%p\n",&d4,&d5);
    d4 = d5;//由于d4已经被构造了,故这里不会从无到有的构造一个对象,也就是说不会调用拷贝构造函数,
            //而仅仅实行数据成员的拷贝
    cout << d4 << endl;
    cout << d5 << endl;*/

    //三、传递对象作为参数和将对象作为返回值
    //Dog d6(110);//调用有参构造函数
    //test(d6);//此调用将会产生以下输出:
//调用了拷贝构造函数
//调用了拷贝构造函数
//析构函数被调用
//析构函数被调用
//现详细说明test(d6);执行的过程:
//d6作为参数传递给test函数时,会从无到有的利用d6构造一个局部对象d,因而调用了一次拷贝构造函数。
//test函数中的return d;语句的执行过程为:
//先从无到有的利用局部对象d构造一个临时对象以作为返回值,此过程调用了一次拷贝构造函数
//然后局部对象d被析构,而临时对象因为没有被引用所以也被析构了,所以调用了两次析构函数
    //Dog d7 = test(d6);//此操作将会产生以下输出:
//调用了拷贝构造函数
//调用了拷贝构造函数
//析构函数被调用
//现详细说明Dog d7 = test(d6);执行的过程:
//d6作为参数传递给test函数时,会从无到有的利用d6构造一个局部对象d,因而调用了一次拷贝构造函数。
//test函数中的return d;语句的执行过程为:
//先从无到有的利用局部对象d构造一个临时对象以作为返回值,此过程调用了一次拷贝构造函数
//然后局部对象d被析构,而临时对象因为被d7引用了,所以生命周期没有结束
    //printf("d6的地址:%p\nd7的地址:%p\n", &d6, &d7);//说明d6和d7是不同的两个对象

    //test1();//现在可以根据上面的分析得出此操作产生的输出结果
    //Dog d8 = test1();
    //printf("d8的地址为:%p\n", &d8);//构造了一个全新的对象


    Dog d9;
    printf("d9的地址为:%p\n", &d9);
    Dog &d10 = test2(d9);//如果一个函数返回的是对象的引用,则必须用引用来接收!
                         //否则,如果用对象来接收,就会利用函数中的引用对象,通过调用拷贝构造函数来构造一个全新的对象。
    printf("d10的地址为:%p\n", &d10);


    //由此证明:
    //1、传递对象作为函数参数和以对象作为函数的返回值时会调用拷贝构造函数;
    //2、所以,可以将函数中的局部对象返回,这样接收返回值时会构造一个与局部对象状态完全一致的全新的对象;
    //3、由于拷贝构造函数的机制,所以c++中不要企图直接通过对象的传递来达到修改对象的目的,只能通过引用或者指针。
    //4、如果一个函数返回的是对象的引用,则必须用引用来接收;否则,如果用对象来接收,
    //   就会利用函数中的引用对象,通过调用拷贝构造函数来构造一个全新的对象。
    system("pause");
}

猜你喜欢

转载自blog.csdn.net/csdn_gddf102384398/article/details/81214439