汇编分析C++class

devtools/2024/11/14 22:10:53/

文章目录

  • this指针不神奇
    • 静态成员方法
  • 构造函数
    • 拷贝构造和移动构造
  • 运算符重载
    • 拷贝赋值和移动赋值
  • 多态机制
    • 虚函数
      • 虚表
        • 对象怎么获取虚表
    • 构造函数禁止为虚函数
    • 继承体系中析构函数必为虚函数
  • 模板对CPU不可见
  • malloc和new
    • free和delete
    • 请配对new和delete
      • free如何确定释放空间的大小

this指针不神奇

我们都知道面向对象是C++和C最大的区别,C++通过将一组属性和一组方法捆绑在一起,分别称为成员属性和成员方法。对于非静态成员方法的访问必须通过实例化对象才能访问,对于非静态成员方法来说一般都会去读写特定的对象属性,因此如何确定读写哪个对象的属性就显得尤为重要了,这个问题通过this指针来解决,所谓this指针就是一个实例化对象的地址,编译器在编译时会自动的向调用非静态成员方法的地方添加一个隐含参数,这个参数就是this,方法内通过this寻址就可以确定目标读写对象

所谓的成员方法只是语法层面的说法,在汇编层面来说本质都是普通的函数

C++代码

c++">class A{
public:void class_fun(){} //形式上无参,实则有一个参数
};
void normal_fun(long a){}
int main(){A a;a.class_fun();normal_fun((long)&a);return 0;
}

汇编代码

A::class_fun():
;...mov QWORD PTR [rbp-8], rdi
;...
normal_fun(long):
;...mov QWORD PTR [rbp-8], rdi
;...
main:
;...lea rax, [rbp-1]mov rdi, raxcall A::class_fun()lea rax, [rbp-1]mov rdi, raxcall normal_fun(long)
;...

通过汇编结果可以很容易看出对于normal_funclass_fun的调用都由寄存器rdi保存参数,进入函数体后从中读取参数;通过对比normal_fun可以判断class_fun的的确确是有一个参数的,这个参数就是this

静态成员方法

根据上述结果不难知道为什么静态成员方法不能访问非静态成员属性了,因为对于静态成员方法来说它没有隐藏的this指针,自然就不知道读写哪一个对象的属性了,但是却可以读写静态成员属性(因为静态成员属性属于而非对象)

C++代码

c++">class A{
public:static void static_fun(){}
};int main(){A::static_fun();return 0;
}

汇编代码

A::static_fun():push rbpmov rbp, rspnoppop rbpret
main:push rbpmov rbp, rspcall A::static_fun()mov eax, 0pop rbpret

汇编结果分析你看不到任何传参操作,即编译器不会为静态成员方法设置this指针

构造函数

构造函数也与普通函数一样,它也具有隐含的参数this,并且它是一个void返回型的函数(void不需要显式声明)

C++ code

c++">class A{
public: A(){x=1;}
protected: int x;
};
class B:public A{
public: B(){y=1;}
protected: int y;
};
int main(){A a;B b;return 0;
}

assembly code

A::A() [base object constructor]:
;...mov QWORD PTR [rbp-8], rdi ;读取thismov rax, QWORD PTR [rbp-8]mov DWORD PTR [rax], 1
;...
B::B() [base object constructor]:
;...mov QWORD PTR [rbp-8], rdi ;读取thismov rax, QWORD PTR [rbp-8]mov rdi, raxcall A::A() [base object constructor]mov rax, QWORD PTR [rbp-8]mov DWORD PTR [rax+4], 1
;...

通过汇编可以看出派生构造函数中会先隐式调用基的构造函数(对于汇编结果的line10~~line12),而后在执行派生自己的构造函数,但是大多数情况下需要程序员在派生的执行构造函数之前显


http://www.ppmy.cn/devtools/134009.html

相关文章

IntelliJ+SpringBoot项目实战(八)--在控制层API中封装响应数据包

在控制层类的接口中一般需要返回响应结果的数据包,如果采用接口返回类型设置为JSONObject,比如 public JSONObject getUserList...){ JSONObject json new JSONObject(); } 通过使用json.put("","")的方式手工设置返回值会比较繁琐&#xf…

图形 2.6 伽马校正

伽马校正 B站视频:图形 2.6 伽马校正 文章目录 伽马校正颜色空间传递函数 Gamma校正校正过程为什么需要校正?CRT与转换函数 为什么sRGB在Gamma 0.45空间? 人对亮度的敏感韦伯定律中灰值 线性工作流不在线性空间下进行渲染的问题统一到线性空…

数据库SQL——连接表达式(JOIN)图解

目录 一、基本概念 二、常见类型 内连接(INNER JOIN): 左连接(LEFT JOIN 或 LEFT OUTER JOIN): 右连接(RIGHT JOIN 或 RIGHT OUTER JOIN): 全连接(FULL…

LabVIEW导入并显示CAD DXF文件图形 程序见附件

LabVIEW导入并显示CAD DXF文件图形 程序见附件 LabVIEW导入并显示CAD DXF文件图形 程序见附件 - 北京瀚文网星科技有限公司 LabVIEW广泛应用于自动化、数据采集、图形显示等领域。对于涉及CAD图形的应用,LabVIEW也提供了一些方法来导入和显示CAD DXF文件&#x…

Diffusion Policy——斯坦福机器人UMI所用的扩散策略:从原理到其编码实现(含Diff-Control、ControlNet详解)

前言 本文一开始是属于此文《UMI——斯坦福刷盘机器人:从手持夹持器到动作预测Diffusion Policy(含代码解读)》的第三部分,考虑后Diffusion Policy的重要性很高,加之后续还有一系列基于其的改进工作 故独立成本文,且写的过程中 …

uni-app收藏按钮组件实现⑬

文章目录 二十一、收藏按钮组件实现一、前端处理二、云函数定义获取数据后前端处理 二十一、收藏按钮组件实现 一、前端处理 收藏图标点击事件内获取用户信息,及文章信息,传递到后端 由于多个界面中都会用到 userInfo 对象,可将 userInfo 对…

机器学习在网络安全中的应用

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 机器学习在网络安全中的应用 机器学习在网络安全中的应用 机器学习在网络安全中的应用 引言 机器学习概述 定义与原理 发展历程 …

【论文阅读】Virtual Compiler Is All You Need For Assembly Code Search

阅读笔记:Virtual Compiler Is All You Need For Assembly Code Search 1. 研究背景 逆向工程:逆向工程需要在庞大的二进制文件中快速定位特定功能(例如恶意行为)。传统方法依赖于经验和启发式算法,效率低下。汇编代码搜索:通过自然语言搜索汇编代码功能,能够更高效地处…