在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. Ubuntu安装samba服务器

    一.安装软件 sudo apt-get install samba 二.配置samba服务器/etc/samba/smb.conf 把默认的配置文件备份,按如下修改配置文件 [global] work ...

  2. 第一章 Qt入门

    1.1Qt 窗口部件 widget,用户界面的一个可视化元素,任意窗口部件都可以作为窗口.可以通过简单的HTML修改丰富样式 1.2建立连接 Qt的窗口部件通过发射信号(signal)来表明一个用户动 ...

  3. 【面向代码】学习 Deep Learning(三)Convolution Neural Network(CNN)

    ========================================================================================== 最近一直在看Dee ...

  4. oracle之Flash Recovery Area全面介绍 (转载)

    1. 设置闪回恢复区闪回恢复区主要通过3个初始化参数来设置和管理 db_recovery_file_dest:指定闪回恢复区的位置db_recovery_file_dest_size:指定闪回恢复区的 ...

  5. CSS布局部分知识总结

    一 切图 通过一个周的切图练习,我发现只有亲自动手后才能通过问题不断加深技术,要熟练掌握HTML页面编写时候时PHOTOSHOP操作. 以下一些知识点在网络布局时也是很重要的. 1.ul标签在谷歌.火 ...

  6. Response 关于浏览器header的方法

    Response.AddHeader   Response.AddHeader使用实例 1.文件下载,指定默认名 Response.AddHeader("content-type" ...

  7. 谈一谈JVM内存JAVA_OPTS参数

    最近几个月,做的性能测试项目中,发现了一些内存方面的问题,其中有涉及到对JBOSS里的JAVA_OPTS配置,例如一下所示: JAVA_OPTS="-server -Xms1536m -Xm ...

  8. C# sql Helper

    using System; using System.Collections; using System.Collections.Generic; using System.Configuration ...

  9. C#中Split分隔字符串的应用(C#、split、分隔、字符串)

    转载地址 .用字符串分隔: using System.Text.RegularExpressions; string str="aaajsbbbjsccc"; string[] s ...

  10. Activiti 5.16用户手册

    From :http://www.mossle.com/docs/activiti/ Table of Contents 1. 简介 协议 下载 源码 必要的软件 JDK 6+ Eclipse Ind ...