从汇编看c++内联函数评估求值
在c++中,一个inline函数实体,在整个class 声明未被完全看到之前,是不会被评估求值的,也就是说,对于类里面内联的成员函数本身的分析,要等到class的声明完全结束之后才开始。
下面试c++源码:
extern int x;//外部声明的x
class X {
public:
float getX() const {
return x;//x绑定的是哪个?
}
private:
float x;//类自身的成员变量x
};
int main() {
X xObj;
float x;
x = xObj.getX();
}
依据上面的规则,内联函数getX绑定的将会是成员变量x(float型)
下面我们只看成员函数getX的汇编码:
?getX@X@@QBEMXZ PROC ; X::getX, COMDAT
; _this$ = ecx ; 5 : float getX() const { push ebp
mov ebp, esp
push ecx;压栈到的目的是为了保存对象xObj的首地址(即this指针)预留空间
mov DWORD PTR _this$[ebp], ecx;寄存器ecx中保留xObj对象首地址,存放到刚才分配的空间 ; 6 : return x; mov eax, DWORD PTR _this$[ebp];将对象xObj对象首地址给eax寄存器
fld DWORD PTR [eax];将对象首地址处内存内容写入到浮点数寄存器ST(0)中,作为返回值 也就是将成员变量x的值返回
;可以看到,x确实绑定的是成员变量 ; 7 : } mov esp, ebp
pop ebp
ret
?getX@X@@QBEMXZ ENDP
但是,这种规则对于成员函数的参数却不是这样。
下面是c++源码:
typedef int length;//全局
class X {
public:
void setI(length x) {//length是什么类型?
i = x;
}
private:
typedef float length;//类成员
length i;
};
int main() {
X xObj;
xObj.setI(1.1);
}
下面通过汇编码看成员变量i和成员函数setI的参数x到底是什么类型
下面是mian函数汇编码:
; 13 : int main() {
push ebp
mov ebp, esp
push ecx;压栈寄存器ecx的目的,是为了为对象xObj预留4byte空间
;这里没有调用xObj默认构造器是因为编译器没有必要为其提供非无用的默认构造器
; 14 : X xObj;
; 15 : xObj.setI(1.1);
push ;将1压栈作为参数传递(虽然传递的是浮点数1.1,但是这里将参数截取为整型,说明参数length确实为int)
lea ecx, DWORD PTR _xObj$[ebp];将对象xObj的首地址给寄存器ecx,作为隐含参数传递给成员函数setI
call ?setI@X@@QAEXH@Z ; 调用setI
; 16 : }
xor eax, eax
mov esp, ebp
pop ebp
ret
_main ENDP
下面是setI函数的汇编码:
?setI@X@@QAEXH@Z PROC ; X::setI, COMDAT
; _this$ = ecx ; 5 : void setI(length x) {//length是什么类型? push ebp
mov ebp, esp
push ecx;压栈寄存器ecx是为保留xObj对象的首地址预留空间
mov DWORD PTR _this$[ebp], ecx;寄存器ecx中存放对象xObj首地址,存放到刚才预留的空间 ; 6 : i = x; fild DWORD PTR _x$[ebp];将参数x(int 型)放入浮点数寄存器ST(0)中, 这条指令专门将整型压入浮点寄存器
mov eax, DWORD PTR _this$[ebp];将对象首地址给寄存器eax
fstp DWORD PTR [eax];将浮点数寄存器ST(0)的内容给对象首地址存内存,即给成员变量i赋值(说明i是浮点型) ; 7 : } mov esp, ebp
pop ebp
ret
?setI@X@@QAEXH@Z ENDP
通过汇编码可以看到,成员函数setI的参数类型在第一次遇见就绑定了类型。
从汇编看c++内联函数评估求值的更多相关文章
- 嵌入式C语言自我修养 10:内联函数探究
10.1 属性声明:noinline & always_inline 这一节,接着讲 __atttribute__ 属性声明,__atttribute__ 可以说是 GNU C 最大的特色.我 ...
- C++内联函数
在C语言中,我们使用宏定义函数这种借助编译器的优化技术来减少程序的执行时间,那么在C++中有没有相同的技术或者更好的实现方法呢?答案是有的,那就是内联函数.内联函数作为编译器优化手段的一种技术,在降低 ...
- iOS OC内联函数 inline的详解
inline 在iOS中的一些框架中,static inline是经常出现的关键字组合. static自不用多说,表示在当前文件中应用,如 static A, 在其它文件中也可以出现static A. ...
- C++内联函数与宏定义
用内联取代宏: 1.内联可调试: 2.可进行类型安全检查或自动类型转换: 3.可访问成员变量. 另外,定义在类声明中的成员函数自动转化为内联函数. 文章(一) 内联函数与宏定义 在C中,常用预处理语句 ...
- C++内联函数、函数模板之于头文件
一.基本说明 C++标准中提到,一个编译单元是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件 ...
- C++中内联函数
目录 什么是内联函数 如何使函数内联 为什么要使用内联函数 inline函数的优缺点分析 什么时候该使用内联函数 正文 在C语言中,我们使用宏定义函数这种借助编译器的优化技术来减少程序的执行时间,那么 ...
- 【转】ios内联函数 inline
ios内联函数 inline 缘由 由于在学习使用UIScrollVew开发的过程中,碰到下面这个属性(设置内边距): @property(nonatomic) UIEdgeInsets scroll ...
- 【C语言】预处理、宏定义、内联函数 _
一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的 ...
- 【C语言】预处理、宏定义、内联函数
一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的汇编 ...
随机推荐
- (转) Java程序员应该知道的10个调试技巧
原地址:http://www.csdn.net/article/2012-09-03/2809495-java-debugging-tips-with-eclipse 调试可以帮助识别和解决应用程序缺 ...
- 如何解决安卓SDK无法下载Package的问题
转载自:http://jingyan.baidu.com/article/8275fc86dbe84046a03cf69d.html 有些用户在安装好Android SDK后,打开Android SD ...
- 【Ecstore】为自建模块添加自定义主题模板
做好ECSOTRE模块后,需在主题中添加模板,而添加模板页面时只有产品分类页.产品详细页.首页等内置模块的模板类型. 下面介绍如何添加一个自定义的模板类型“buildings”. 一.修改(建议复制到 ...
- 【转】实战Nginx与PHP(FastCGI)的安装、配置与优化
原文连接:http://ixdba.blog.51cto.com/2895551/806622 原文作者:南非蚂蚁 转载注明以上信息 一.什么是 FastCGIFastCGI是一个可伸缩地.高速地在H ...
- 【0】python核心编程,第二章
1.print语句也支持将输入重定向到文件,示例: logfile = open('/tmp/mylog.txt', 'a') print >> logfile, 'Fatal error ...
- 超级密码(dfs)
超级密码233 Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- CSS3匹配屏幕横竖状态
@media是css3中新定义的,功能非常强大,下面简单讲解一下用css3的@media orientation匹配手机屏幕是横屏还是竖屏. 顾名思义PC是无法匹配横竖屏的,所以orientation ...
- Windows7里的“计算器”你真的会用吗?
“计算器”是不同Windows版本中的必备工具,虽然功能单一,但的确是人们日常工作中不可缺少的辅助工具,本文就来谈谈它的使用. 一.标准型和科学型两种面板 我们既可从Windows附件菜单中启动它,也 ...
- Delphi泛型评测(30篇)
http://www.cnblogs.com/jxgxy/category/216671.html
- C# Directory类
Directory类 是一个静态类,常用的地方为创建目录和目录管理. 一下来看看它提供的操作. 1.CreateDirectory 根据指定路径创建目录.有重载,允许一次过创建多个目录. 2.Dele ...