C++对象内存布局,this指针,对象作为参数,作为返回值
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 <iostream>
#include "mytest.h" int main()
{
TestClass test;
test.setNum(); 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 -
.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
.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: call sub_411055
.text: add esp, 0Ch
.text:0041280C push offset Str ; "Hello World!\n"
.text: mov eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text: push eax ; int
.text: call sub_411226
对象作为返回值
1、分配一个临时对象空间 main_object;
2、把临时对象入栈
3、调用返回局部对象的函数
在返回局部对象的函数里面
fun_object;
一些局部变量操作
返回的时候用用局部对象作为参数,传入main_object对象的this指针
调用复制构造函数
用EAX返回this指针
tt=main_object;
一下转自:https://blog.csdn.net/qq_22660775/article/details/89854545
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的构造函数 //构造主方法内的对象t
B的构造函数 //构造fun2内的局部对象b
B的复制构造函数 //将func2的局部对象复制到一个临时对象
B的析构函数 //析构局部对象b
B的赋值操作符 //使用临时对象初始化t
B的析构函数 //析构临时对象
B的析构函数 //析构对象t
由于 t 的初始化采用的是operator=操作符,operator=要求必须使用一个已经创建好了的对象对左值进行复制,所以此时必须先形成一个临时对象,然后将临时对象赋值给 t
运行测试函数test2(),其运行结果为:
B的构造函数 //构造fun2内的局部对象b
B的复制构造函数
B的析构函数
B的析构函数
由于 t 是通过复制构造函数进行初始化的。复制构造函数初始化要求左值是一个已有对象,而非创建好了的对象,因此此时不需要创建一个临时对象
C++对象内存布局,this指针,对象作为参数,作为返回值的更多相关文章
- c++ 指针做为参数和返回值
指针参数 返回值是指针 一.指针作参数形式的函数 //计算x的平方 x*x void square(int *x) { int a=*x; *x=a*a; } 二.指针作返回值的函数 int *squ ...
- Java对象内存布局
本文转载自Java对象内存布局 导语 首先直接抛出问题 Unsafe.getInt(obj, fieldOffset)中的fieldOffset是什么, 类似还有compareAndSwapX(obj ...
- JVM-对象及对象内存布局
目录 前言 类与对象 对象类二分模型 对象 对象内存布局 JOL工具 对象头 Mark Word 类型句柄 对象头与锁膨胀 无锁 偏向锁 轻量级锁 重量级锁 重量级锁降级 实例数据 填充 对象生命周期 ...
- 图说C++对象模型:对象内存布局详解
0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看. 本文的结论都在VS2013上得到验证.不同的编译器在内存布局的细节上可能有 ...
- c++ 对象内存布局详解
今天看了的,感觉需要了解对象内存的问题.参考:http://blog.jobbole.com/101583/ 1.何为C++对象模型? 引用<深度探索C++对象模型>这本书中的话: 有两个 ...
- c++对象内存布局
这篇文章我要简单地讲解下c++对象的内存布局,虽然已经有很多很好的文章,不过通过实现发现有些地方不同的编译器还是会有差别的,希望和大家交流. 在没有用到虚函数的时候,C++的对象内存布局和c语言的st ...
- 从C++对象内存布局和构造过程来具体分析C++中的封装、继承、多态
一.封装模型的内存布局 常见类对象的成员可能包含以下元素: 内建类型.指针.引用.组合对象.虚函数. 另一个角度的分类: 数据成员:静态.非静态 成员函数:静态.非静态.虚函数 1.仅包含内建类型的场 ...
- c++对象内存布局的理解
我对c++对象内存布局的理解 引言 结合网上的一些资料,通过自己的一番摸索,得出了一点个人见解.现在写下来,希望与各位同学共同探讨,共同进步. 以下所有代码均是在VS2012下测试. 一个普通的基 ...
- 好文章系列C/C++——图说C++对象模型:对象内存布局详解
注:收藏好文章,得出自己的笔记,以查漏补缺! ------>原文链接:http://blog.jobbole.com/101583/ 前言 本文可加深对C++对象的内存布局.虚表指针.虚 ...
- 使用sos查看.NET对象内存布局
前面我们图解了.NET里各种对象的内存布局,我们再来从调试器和clr源码的角度来看一下对象的内存布局.我写了一个测试程序来加深对.net对象内存布局的了解: using System; using S ...
随机推荐
- Golang 传递任意类型的切片
肯定有这样的一种场景,写一个函数,该函数可以接收任意类型的切片,完成相应的功能. 就好比这种情况 intSlice := []int{1,2,3,4,5,6,7,8} strSlice := []st ...
- VC++如何利用Matlab2014b的图形引擎进行绘图
VC++如何利用Matlab的图形引擎 在Visual C++ 2015 工程中使用 Matlab2014b 提供的图形引擎进行绘图的详细过程. 问题来源: 有时候用C++写一些演示程序,有数据可视化 ...
- Parameter 0 of method sqlSessionTemplate in org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration required a single bean, but 2 were found:
Parameter 0 of method orderSqlSessionFactory in com.config.MultipleDBConfig required a single bean, ...
- P2801 教主的魔法 (线段树)
题目 P2801 教主的魔法 解析 成天做水题 线段树,第一问区间加很简单 第二问可以维护一个区间最大值和一个区间最小值,若C小于等于区间最小值,就加上区间长度,若C大于区间最大值,就加0 ps:求教 ...
- React Native 开发豆瓣评分(七)首页组件开发
首页内容拆分 看效果图,首页由热门影院.豆瓣热门.热门影视等列表组成,每个列表又由头加横向滑动的 电影海报列表构成. 所以可以先把页面的电影海报.评分.列表头做成组件,然后在使用 ScrollView ...
- JavaWeb 之 Listener:监听器
一.概述 1.事件监听机制 事件: 一件事情 事件源: 事件发生的地方 监听器: 一个对象 注册监听: 将事件.事件源.监听器绑定在一起. 2.监听器概念 当事件源上发生某个 ...
- SpringBoot 传入JSON对象参数
1.请求参数格式必须是正确的JSON. 2.在入参中使用注解@RequestBody,用于接收JSON参数,使其自动转对象 3.关于lombok在此产生的一点小坑,@Builder对@RequestB ...
- Vue+Django项目部署
本地项目配置 1 复制 luffy/settings/dev.py为prop.py 修改luffy/settings/prop.py中以下几项 (1) allow_hosts ALLOWED_HOST ...
- 【RocketMQ异常】Caused by: com.aliyun.openservices.shade.com.alibaba.rocketmq.client.exception.MQClientException: No route info of this topic, message-service-topic-testf
一.异常信息 -- ::-thread-] ERROR c.x.x.r.service.producer.ali.AliMQProducerProcess.sendMessageFromQueue(A ...
- 五、Linux_ping命令
ping命令用法为:“ping 参数 目标主机”.其中参数为零到多个,目标主机可以是IP或者域名. 1.每隔0.6秒ping一次,一共ping 5次: [root@aiezu.com ~]# ping ...