在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++内联函数评估求值的更多相关文章

  1. 嵌入式C语言自我修养 10:内联函数探究

    10.1 属性声明:noinline & always_inline 这一节,接着讲 __atttribute__ 属性声明,__atttribute__ 可以说是 GNU C 最大的特色.我 ...

  2. C++内联函数

    在C语言中,我们使用宏定义函数这种借助编译器的优化技术来减少程序的执行时间,那么在C++中有没有相同的技术或者更好的实现方法呢?答案是有的,那就是内联函数.内联函数作为编译器优化手段的一种技术,在降低 ...

  3. iOS OC内联函数 inline的详解

    inline 在iOS中的一些框架中,static inline是经常出现的关键字组合. static自不用多说,表示在当前文件中应用,如 static A, 在其它文件中也可以出现static A. ...

  4. C++内联函数与宏定义

    用内联取代宏: 1.内联可调试: 2.可进行类型安全检查或自动类型转换: 3.可访问成员变量. 另外,定义在类声明中的成员函数自动转化为内联函数. 文章(一) 内联函数与宏定义 在C中,常用预处理语句 ...

  5. C++内联函数、函数模板之于头文件

    一.基本说明 C++标准中提到,一个编译单元是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件 ...

  6. C++中内联函数

    目录 什么是内联函数 如何使函数内联 为什么要使用内联函数 inline函数的优缺点分析 什么时候该使用内联函数 正文 在C语言中,我们使用宏定义函数这种借助编译器的优化技术来减少程序的执行时间,那么 ...

  7. 【转】ios内联函数 inline

    ios内联函数 inline 缘由 由于在学习使用UIScrollVew开发的过程中,碰到下面这个属性(设置内边距): @property(nonatomic) UIEdgeInsets scroll ...

  8. 【C语言】预处理、宏定义、内联函数 _

    一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件   1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的 ...

  9. 【C语言】预处理、宏定义、内联函数

    一.由源码到可执行程序的过程 1. 预处理: 源码经过预处理器的预处理变成预处理过的.i中间文件 1 gcc -E test.c -o test.i 2. 编译: 中间文件经过编译器编译形成.s的汇编 ...

随机推荐

  1. Lucene学习总结之六:Lucene打分公式的数学推导

    在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下.因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数. Lucene ...

  2. Javascript经典实例 - 字符串

    1] 'this is a string'这是字符串直接量,new String('this is a string')这是字符串对象,字符串对象可以用字符串对象所带的属性和方法,直接量在“表面上”也 ...

  3. docker镜像与容器存储结构分析

    注意:转载请注明出处:http://www.programfish.com/blog/?p=9 Docker是一个开源的应用容器引擎,主要利用linux内核namespace实现沙盒隔离,用cgrou ...

  4. 1004 Anagrams by Stack

    考察DFS的应用,用栈描述字符串的变化过程. #include <stdio.h> #include <string.h> int len1,len2; ],str2[],st ...

  5. C# Assembly类_反射

    System.Reflection.Assembly类是一个比较常用到的类,在反射中就经常用到. 由于这个类实在有太多的字段.属性与方法.实在不想将一个个属性方法从MSDN复制出来然后逐个属性.方法敲 ...

  6. 转:ReportViewer控件使用方法

    a. ReportViewer关联Report1.rdlc的简单呈现b. 对带有报表参数的Report1.rdlc的呈现c. 利用程式生成的DataSet 填充报表d. 调用存储过程 生成DataSe ...

  7. nginx监听端口和反向代理端口的权限问题

    Linux的SELinux安全性控制除作用于文件系统外还作用于端口,这使得那些作为服务启动的进程只能在规定的几个端口上监听.为叙述方便我们称之为受控端口. nginx监听端口 要查看当前有哪些受控端口 ...

  8. convertView

    [convertView] 参考:https://zhidao.baidu.com/question/423895201122905772.html

  9. 【转】__attribute__机制介绍

    1. __attribute__ GNU C的一大特色(却不被初学者所知)就是__attribute__机制. __attribute__可以设置函数属性(Function Attribute).变量 ...

  10. Scala--样例类(case)详解

    概述: case类在模式匹配和actor中经常使用到,当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了一系列方法且带来了不少好处,如下: 1.实现了apply方法,意味 ...