类对象结构

前言:对于类的一些构造之前有一定的了解,但到具体的技术细节,总会有些纰漏,经过多方查阅,有了一些新的感悟,在这里做一个总结,方便之后翻阅。
首先声明一个简单类型MyClass,做测试用:

#include <stdio.h>
#include <iostream>
using namespace std;
class MyClass
{
private:
    int i; //实例对象,用于模拟类信息
    int *p; //实例指针对象,用于模拟类信息
public:
    static int count; //静态变量,用于统计实际产生多少个对象
    MyClass(int i)
    {
        cout << "Enter MyClass Creater:" << this << endl;
        count++; //每生成一个对象,统计count就+1
        p = new int;
        this->i = i;
    }
    ~MyClass()
    {
        cout << "Enter MyClass Deleter:" << this << endl;
        count--; //每销毁一个对象,统计count就-1
        if (NULL != p)
        {
            delete p;
        }
    }
    MyClass(const MyClass& myObject)
    {
        cout << "Enter MyClass Coper:" << this << endl;
        this->i = myObject.i;
        count++; //复制对象时,统计数+1
        p = new int;
        *p = *(myObject.p);
    }
    MyClass & operator=(const MyClass& myObject)
    {
        cout << "Enter MyClass Assigner:" << this << endl;
        this->i = myObject.i; //对象赋值时,统计数不需要变动
        return *this;
    }
};
int MyClass::count = 0;

一、当对象通过形参传入其他函数中时(按照注释的顺序):

MyClass fun01(MyClass myObject) //2)myObject作为形参传入,调用复制构造函数,count=2
{
    return myObject; //3)return返回时会cope到一个临时变量,进入复制构造函数,count=3,之后因为fun01的myobject在栈上,会调用调用此处的myobject的析构函数,所以count--之后,count=2
}

int main()
{
    MyClass myObject(1); //1)count=1
    MyClass myObject2 = fun01(myObject); //4)此处没有对象接收函数返回值时,会调用临时变量的析构函数,count=1,
    return 0;
}//5)此处析构掉栈上的对象main的myObject,count=0

可以想象,当对象参数通过引用的方式传入的时候,由于不会复制对象,所以count最大值只会到2。

二、复制构造函数与赋值构造函数

int main()
{
    MyClass myObject1(1);
    MyClass myObject2=myObject1; //对象myObject2本身不存在,调用复制构造函数,最后是两个对象

    MyClass myObject3(1);
    MyClass myObject4(2);
    myObject4 = myObject3; //对象myObject4本身存在,调用赋值构造函数,最后是两个对象
    return 0;
}

另外,通过对象初始化的话也是调用复制构造函数(MyClass myObjectx(myObject4))。

三、为什么要重写复制构造函数

class MyClass2
{
private:
    int i; //实例对象,用于模拟类信息
    int *p; //实例指针对象,用于模拟类信息
public:
    static int count; //静态变量,用于统计实际产生多少个对象
    MyClass2(int i)
    {
        cout << "Enter MyClass2 Creater:" << this << endl;
        count++; //每生成一个对象,统计count就+1
        p = new int;
        this->i = i;
    }
    ~MyClass2()
    {
        cout << "Enter MyClass2 Deleter:" << this << endl;
        count--; //每销毁一个对象,统计count就-1
        if (NULL != p)
        {
            delete p;
        }
    }
};

int MyClass2::count = 0;

int main()
{
    MyClass2 myObject5(1);
    MyClass2 myObject6 = myObject5; //对象myObject6本身不存在,调用默认复制构造函数,最后是一个对象
    return 0;
}

编译器会默认生成复制构造函数,但是默认生成的复制构造函数是的按位复制对象(浅复制),并不会生产新的对象(myObject6就是myObject5)。当对象内部含有指针对象(MyClass2的p),造成复制出来的的对象内部的指针类型数据(myObject6->p)和原本对象内部的指针类型数据(myObject5->p)值一致,导致所指向的目标一致(*myObject6->p和*myObject5->p),结果导致第一个对象delete之后,第二个对象重复delete。

另外,默认复制构造函数导致MyClass2::count并不会增加。

所以我们需要创建自定义的复制构造函数进行深复制(参看MyClass)。

之后若有其他关于对象结构的内容,会在此处补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值