对象(探讨对象不适合作为参数和返回值,对象的指针可以的原因)

对象

​ 类的一个实例化。对象中的成员定义从低地址到高地址

1. 对象作为函数参数

​ 对象传参时先将对象中的所有数据进行备份(复制),将复制的数据作为形参传递到调用函数中使用

隐患:拷贝数据中有申请的内存空间,浅拷贝只会拷贝地址不会拷贝数据,在调用函数中会调用一次析构函数释放复制出来的临时对象,在main函数中还会调用一次析构函数释放本来的对象,两次析构,造成内存释放错误

解决方法

  1. 使用深拷贝
  2. 使用引用计数:进入复制构造函数时,记录类对象被复制引用的次数。当对象被销毁时,检查引用计数中保存的引用复制次数是否为0。是,则释放申请的资源,否则引用计数减1

2. 对象指针作为函数参数

​ 传递的数据是指针类型,在函数内的操作都是针对原对象的,不存在对象被复制的问题。因此在函数进入和退出时不会调用构造函数和析构函数,也就不存在资源释放的错误隐患

3. 对象作为返回值

​ 基本数据类型(双精度浮点型以及非标准的__int64类型除外)作为返回值时,通过寄存器eax来保存返回的数据

对象属于自定义类型,寄存器eax无法保存对象中的所有数据

  1. 在main函数中预留返回对象的栈空间,获取返回对象的栈空间首地址,将申请的返回对象的首地址作为参数压栈,以获得返回对象的数据
  2. 进入函数后申请返回对象使用的栈空间,退出函数时,将返回对象中数据复制到临时的栈空间中,以这个临时的首地址作为返回值
  3. 在函数调用结束后进行了数据复制,将函数中的局部对象的数据复制到这个返回对象的空间中,再将这个返回对象复制给目标对象,

注意:此处的返回对象是临时存在的,即临时对象,作用域仅限单条语句

4. 临时对象

​ 调用返回对象的函数时,如 GetCReturn().m_nNumber,此时函数已经退出,其栈帧也被关闭。只能由函数的调用方准备空间,建立临时对象,然后将函数中的局部对象复制给临时对象,再把这个临时对象交给调用方去操作。

​ 当临时对象被销毁时,会执行析构函数,如果析构函数中有对资源释放的处理,可能造成同一个资源多次释放的错误发生

注意
1)对象作为函数参数,可以传递对象类型的指针

2)当对象作为返回值,如果对象在函数内被定义为局部变量,则不可返回此对象的首地址或引用,以避免返回已经被释放的局部变量

posted @ 2023-02-04 22:49  修竹Kirakira  阅读(23)  评论(0编辑  收藏  举报