类的作用域

来源:互联网 发布:淘宝上怎么看淘宝达人 编辑:程序博客网 时间:2024/05/16 23:36

全局对象和静态对象

构造函数的调用

全局对象和静态对象相同,构造函数在 main 函数之前的 _cinit 中的 _initterm 中调用。从栈回溯中,可以看到调用的过程是由 _initterm => $E4 => $E1 => 构造函数

这里写图片描述

析构函数的调用

atexit() 函数介绍

该函数是一个 C 标准函数,参数中填入某个函数指针,在 main 函数退出后将利用函数指针调用该函数。如果注册了多个函数,调用顺序为先注册的后调用。

析构函数调用过程

在 _initterm 中调用构造函数时,同时也会使用 atexit 注册析构函数。而 atexit 中会用一个全局函数指针 __onexitbegin 保存 atexit 中注册的函数。在进程结束时,在 exit 函数内的 doexit 函数内将有一段代依次调用 __onexitbegin 内的函数指针数组,调用析构函数。

_initterm 对对象构造的操作

这里写图片描述

在逆向中的使用

我们可以通过在 IDA 中查找 atexit 函数,观察是谁调用了这个函数,从而对全局对象的信息一网打尽。

局部静态对象

局部静态对象十分容易识别,会有一个标志位,在第一次初始化后,就不会再构造

这里写图片描述

对象作为参数

对象在函数调用前调用拷贝构造函数;函数退出后,针对参数,调用析构函数。

这里写图片描述

这里写图片描述

对象作为返回值

情况一

CTest t = GetObj();

将 t 的地址作为隐含参数传递给 GetObj,在 GetObj 内完成了拷贝构造。不会产生临时对象。

这里写图片描述

这里写图片描述

情况二

  CTest t;  t = GetObj();

会产生一个临时对象作为隐含参数传入到函数内,并在函数退出前,在函数内调用拷贝构造。执行完毕后,如果在 CTest 类中定义了 “=” 的运算符重载,则调用;否则根据对象成员逐个赋值(浅拷贝)。

这里写图片描述

情况三

CTest &refTest = GetObj(); 

会产生一个 无名对象 作为隐含参数传入到函数内,并在函数退出前,在函数内调用拷贝构造。

这里写图片描述

这里写图片描述

这里写图片描述

虽然指针和引用的区别不大,但是在上面的代码中,使用指针和引用是有区别的。此时产生的是临时对象,在退出函数作用域后会立即析构。此时如果在使用变量 p 调用成员函数,或许会出问题,因为该对象已经被析构。这段代码是错误代码。

堆对象

malloc 和 new 的区别

new 堆 malloc 做了封装,但是创建对象时使用 malloc 时,编译器不会自动为此生成构造函数。

创建单个对象

这里写图片描述

创建对象数组

在堆中申请对象数组时,只能使用无参构造。在构造过程中,使用了名为向量化构造函数迭代器…申请的空间中,第一个字段存储这个这个数组的个数,所以释放对象时需要使用 delete[],依次析构数组中的对象。

这里写图片描述

这里写图片描述

原创粉丝点击