博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++对象内存布局,this指针,对象作为参数,作为返回值
阅读量:4646 次
发布时间:2019-06-09

本文共 3776 字,大约阅读时间需要 12 分钟。

 

class TestClass{public:    void setNum(int num)    {        m_num1 = num;    }    int getNum()    {        return m_num1;    }private:    int m_num1;    int m_num2;};

 

#include "pch.h"#include 
#include "mytest.h"int main(){ TestClass test; test.setNum(100); printf("sizeof testClass=%d,num = %d\n", sizeof(test), test.getNum()); std::cout << "Hello World!\n"; }

输出:sizeof testClass=8,num = 100

 

没有虚函数时,test变量在内存中的分布

 

若存在虚函数

class TestClass{public:    virtual void setNum(int num)    {        m_num1 = num;    }    virtual int getNum()    {        return m_num1;    }private:    int m_num1;    int m_num2;};

 

 

 

我们用IDA打开看一下反汇编

ext:004127B0 var_D8          = byte ptr -0D8h.text:004127B0 var_14          = byte ptr -14h.text:004127B0 var_4           = dword ptr -4.text:004127B0.text:004127B0                 push    ebp.text:004127B1                 mov     ebp, esp.text:004127B3                 sub     esp, 0D8h.text:004127B9                 push    ebx.text:004127BA                 push    esi.text:004127BB                 push    edi.text:004127BC                 lea     edi, [ebp+var_D8].text:004127C2                 mov     ecx, 36h.text:004127C7                 mov     eax, 0CCCCCCCCh.text:004127CC                 rep stosd.text:004127CE                 mov     eax, ___security_cookie.text:004127D3                 xor     eax, ebp.text:004127D5                 mov     [ebp+var_4], eax.text:004127D8                 mov     ecx, offset unk_41E009.text:004127DD                 call    sub_411299.text:004127E2                 lea     ecx, [ebp+var_14]   // ecx 保存this指针,通过this指针地址偏移来调用类成员.text:004127E5                 call    sub_411311.text:004127EA                 push    100.text:004127EC                 lea     ecx, [ebp+var_14].text:004127EF                 call    sub_41113B.text:004127F4                 lea     ecx, [ebp+var_14].text:004127F7                 call    sub_4112A8.text:004127FC                 push    eax.text:004127FD                 push    0Ch.text:004127FF                 push    offset aSizeofTestclas ; "sizeof testClass=%d,num = %d\n".text:00412804                 call    sub_411055.text:00412809                 add     esp, 0Ch.text:0041280C                 push    offset Str      ; "Hello World!\n".text:00412811                 mov     eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream
> std::cout.text:00412816 push eax ; int.text:00412817 call sub_411226

 

对象作为返回值

1、分配一个临时对象空间 main_object;
2、把临时对象入栈
3、调用返回局部对象的函数

在返回局部对象的函数里面

fun_object;
一些局部变量操作
返回的时候用用局部对象作为参数,传入main_object对象的this指针
调用复制构造函数
用EAX返回this指针

tt=main_object;

 

一下转自:

C++规定当函数返回的是非引用类型时,函数会创建临时对象(temporary object),函数返回的就是这个临时对象。在求解表达式时,如果需要一个地方存储其运算结果,编译器会创建一个没有命名的对象,这就是临时对象。浅显的说,当你调用了函数,函数会 return一个值 那么这个值总得有存放的地方吧,编译器就把会把值存放在一个没有命名法临时对象中。

我们举个例子来说明一下,首先定义一个类:

class B {public: B(){ cout << "B的构造函数" << endl; } B(int i){ cout << "带int型参数的B的构造函数" << endl; } B(const B &ano){ cout << "B的复制构造函数" << endl; } B& operator=(const B& rhs){ cout << "B的赋值操作符" << endl; return *this; } virtual ~B(){ cout << "B的析构函数" << endl; } };

 

定义一个函数:

B func2(){	B b; return b; }

上面的函数返回一个非引用类型的变量,我们写两个测试函数,来看看返回一个非引用类型的变量会发生什么

void test1() { B t; t = func2(); } void test2() { B t = func2(); }

运行测试函数test1(),其运行结果为:

B的构造函数 //构造主方法内的对象tB的构造函数 //构造fun2内的局部对象bB的复制构造函数 //将func2的局部对象复制到一个临时对象B的析构函数 //析构局部对象bB的赋值操作符 //使用临时对象初始化tB的析构函数 //析构临时对象B的析构函数 //析构对象t

由于 t 的初始化采用的是operator=操作符,operator=要求必须使用一个已经创建好了的对象对左值进行复制,所以此时必须先形成一个临时对象,然后将临时对象赋值给 t

运行测试函数test2(),其运行结果为:

B的构造函数 //构造fun2内的局部对象b  B的复制构造函数   B的析构函数B的析构函数

由于 t 是通过复制构造函数进行初始化的。复制构造函数初始化要求左值是一个已有对象,而非创建好了的对象,因此此时不需要创建一个临时对象

 

转载于:https://www.cnblogs.com/xiangtingshen/p/11400070.html

你可能感兴趣的文章
1035等差数列末项计算
查看>>
CDMA鉴权
查看>>
ASP.NET MVC Identity 兩個多個連接字符串問題解決一例
查看>>
过滤器与拦截器区别
查看>>
USACO 1.5.4 Checker Challenge
查看>>
第二阶段站立会议7
查看>>
[18]Debian Linux Install GNU GCC Compiler and Development Environment
查看>>
JAVA多线程
查看>>
ACE(Adaptive Communication Environment)介绍
查看>>
delphi 更改DBGrid 颜色技巧
查看>>
python编码问题
查看>>
POJ 2031 Building a Space Station
查看>>
面向对象1
查看>>
编程开发之--java多线程学习总结(5)
查看>>
register_globals(全局变量注册开关)
查看>>
as3调用外部swf里的类的方法
查看>>
如何让 zend studio 10 识别 Phalcon语法并且进行语法提示
查看>>
任意阶幻方(魔方矩阵)C语言实现
查看>>
视频教程--ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库
查看>>
第五次作业
查看>>