从汇编看c++中引用与指针的使用分析

2014-08-13  来源:本站原创  分类:C 语言  人气:0 

在c++中,引用和指针具有相同的作用,都可以用来在函数里面给变函数外面对象或者变量的值,下面就来看他们的原理

首先是引用情形下的c++源码:

void add(int a, int b, int&c) {
    c = a + b;
}

int main() {
    int a = 1;
    int b = 2;
    int c = 0;
    add(a, b, c);

}

下面是main对应的汇编码:


复制代码 代码如下:

; 6    : int main() {
    push    ebp
    mov    ebp, esp
    sub    esp, 12                    ; 为该调用函数的栈空间预留12byte,用来存储局部变量a,b, c
; 7    :     int a = 1;
    mov    DWORD PTR _a$[ebp], 1;初始化a _a$为a存储空间地址相对于ebp基址的偏移量
; 8    :     int b = 2;
    mov    DWORD PTR _b$[ebp], 2;初始化b _b$为b存储空间地址相对于ebp基址的偏移量
; 9    :     int c = 0;
    mov    DWORD PTR _c$[ebp], 0;初试化c _c$为c存储空间地址相对于ebp基址的偏移量
; 10   :     add(a, b, c);
    lea    eax, DWORD PTR _c$[ebp]; 获取c存储空间相对于ebp基址的偏移量(即c存储单元的偏移地址),放在寄存器eax中
    push    eax;保存c存储空间的偏移量到堆栈中
    mov    ecx, DWORD PTR _b$[ebp];将b存储空间里面的值(即b的值)放在寄存器ecx中
    push    ecx;保存b存储空间的值到堆栈中
    mov    edx, DWORD PTR _a$[ebp];将a存储空间里面的值(即a的值)放在寄存器edx里面
    push    edx;保存a存储空间的到堆栈

    ;上面push eax push ecx push edx在栈里面存储了原来局部变量a,b,c的值,只不过对于c来说,存储的是c存储空间的偏移地址
    ;因此,对于a,b来说,也就是将他们的值得一份拷贝存了起来,也就是传值;而c只是存储了自己存储空间的偏移地址,也就是传地址
    call    [email protected]@[email protected]            ; 调用add函数,上面的语句已经为传递参数做好了准备
    add    esp, 12                    ; 由于刚才为调用函数add传递参数进行了压栈,这里释放栈空间,即释放参数
                                ;这就是为什么函数调用完成后局部变量和参数无效的原因,因为他们的空间被释放了
; 11   :
; 12   : }
    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

下面是函数add对应的汇编码:


复制代码 代码如下:

; 1    : void add(int a, int b, int&c) {
    push    ebp
    mov    ebp, esp
; 2    :     c = a + b;
    mov    eax, DWORD PTR _a$[ebp];取参数a的值到寄存器eax中
    add    eax, DWORD PTR _b$[ebp];取参数b的值与eax中a的值相加,结果放到eax中
    mov    ecx, DWORD PTR _c$[ebp];去c的偏移地址放到寄存器ecx中
    mov    DWORD PTR [ecx], eax;将eax中的结果写到由ecx指定的地址单元中去,即c所在存储单元
; 3    : }
    pop    ebp
    ret    0

从上面可以看到,对于传值,c++确实传的是一份值拷贝,而对于引用,虽然是传值的形式,但是其实编译器内部传递的是值得地址

下面是指针的情形的c++源码:

复制代码 代码如下:

void add(int a, int b, int* c) {
    *c = a + b;
}

int main() {
    int a = 1;
    int b = 2;
    int c = 0;
    add(a, b, &c);

}

mian函数对应的汇编码:


复制代码 代码如下:

; 6    : int main() {
    push    ebp
    mov    ebp, esp
    sub    esp, 12                    ;
; 7    :     int a = 1;
    mov    DWORD PTR _a$[ebp], 1
; 8    :     int b = 2;
    mov    DWORD PTR _b$[ebp], 2
; 9    :     int c = 0;
    mov    DWORD PTR _c$[ebp], 0
; 10   :     add(a, b, &c);
    lea    eax, DWORD PTR _c$[ebp]
    push    eax
    mov    ecx, DWORD PTR _b$[ebp]
    push    ecx
    mov    edx, DWORD PTR _a$[ebp]
    push    edx
    call    [email protected]@[email protected]            ; add
    add    esp, 12                    ;
; 11   :
; 12   : }
    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

add函数对应的汇编码:


复制代码 代码如下:

; 1    : void add(int a, int b, int* c) {
    push    ebp
    mov    ebp, esp
; 2    :     *c = a + b;
    mov    eax, DWORD PTR _a$[ebp]
    add    eax, DWORD PTR _b$[ebp]
    mov    ecx, DWORD PTR _c$[ebp]
    mov    DWORD PTR [ecx], eax
; 3    : }
    pop    ebp
    ret    0

可以看到,指针和引用的汇编码一样,因此两者的作用也一样

相关文章
  • 从汇编看c++中引用与指针的使用分析 2014-08-13

    在c++中,引用和指针具有相同的作用,都可以用来在函数里面给变函数外面对象或者变量的值,下面就来看他们的原理 首先是引用情形下的c++源码: void add(int a, int b, int&c) { c = a + b; } int main() { int a = 1; int b = 2; int c = 0; add(a, b, c); } 下面是main对应的汇编码: 复制代码 代码如下: ; 6 : int main() { push ebp mov ebp, esp sub e

  • 从汇编看c++中多态的应用 2015-02-20

    本篇文章是对c++中多态的应用进行了详细的分析介绍,需要的朋友参考下 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的一项重要功能就是初始化vptr指针,这是保证多态性的关键步骤. 构造函数初始化vptr指针 下面是c++源码: class X { private: int i; public: X(int ii) { i = ii; } virtual void set(int ii) {//虚函数 i = ii; } }; int main() { X x(1); } 下面

  • c++中引用和指针的区别和联系 2014-03-09

    许多人对于引用和指针的区别与联系很纠结(包括我在内O(∩_∩)O哈哈~),最近看到一篇关于引用和指针区别和联系的文章,感觉茅塞顿开,在这里和大家分享下 C++中的引用和指针 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用是某块内存的别名(java中的引用其实也是别名的意思). ★ 区别: 1. 指针是一个实体,而引用仅是个别名: 2. 引用使用时无需解引用(*),指针需要解引用: 3. 引用只能在定义时被初始化一次,之后不可变:指针可变: 引用"从一而终&

  • C++中引用和指针的区别[转载] 2013-10-13

    下面用通俗易懂的话来概述一下: 指针-对于一个类型T,T*就是指向T的指针类型,也即一个T*类型的变量能够保存一个T对象的地址,而类型T是可以加一些限定词的,如const.volatile等等.见下图,所示指针的含义: 引用-引用是一个对象的别名,主要用于函数参数和返回值类型,符号X&表示X类型的引用.见下图,所示引用的含义: 2.指针和引用的区别 首先,引用不可以为空,但指针可以为空.前面也说过了引用是对象的别名,引用为空--对象都不存在,怎么可能有别名!故定义一个引用的时候,必须初始化.因此

  • 从汇编看c++中默认构造函数的使用分析 2014-12-28

    c++中,如果为一个类没有明确定义一个构造函数,那么,编译器就会自动合成一个默认的构造函数.下面,通过汇编程序,来看一下其真实情况 c++中的源程序: class X { private: int i; }; int main() { X x; } 上面的类X没有定义构造函数,仅仅有一个int i. 下面为其汇编程序: 复制代码 代码如下: ; 7 : int main() { push ebp;ebp为一个寄存器,总是指向一个函数调用堆栈的栈底,作为基址,用偏移量来访问该调用栈上的变量,但这里

  • 从汇编看c++中变量类型的深入分析 2014-06-16

    本篇文章是对c++中的变量类型进行了详细的分析介绍.需要的朋友参考下 全局变量的生命期和可见性是整个程序的运行期间,下面就来用汇编来看一下实际情况: c++源码: int i = 2;//全局变量 int main() { int j = i; } 下面是汇编代码: 复制代码 代码如下: PUBLIC [email protected]@3HA ; i _DATA SEGMENT [email protected]@3HA DD 02H ; 全局变量i内存空间 _DATA ENDS PUBLIC _main ; Function compile fl

  • 从汇编看c++中extern关键字的使用 2014-08-27

    本篇文章介绍了,在c++中extern关键字的使用概述,需要的朋友参考下 在c++中,extern关键字用来声明变量和函数,在声明函数的时候,有和没有extern的效果一样,即下面两条语句具有同样的效果: extern void fun(); void fun(); 但是对于变量,有和没有extern就有区别,当有extern时,只是告知编译器存在这个变量,编译器并不为该变量分配存储空间,即真正的声明:若没有extern,则在声明的同时,编译器也为该变量分配存储空间. 下面是有extern的情形

  • 从汇编看c++中函数里面的static关键字的使用说明 2014-10-02

    c++中的static关键字使得函数里面的局部变量的存活期不在局限于函数里面,而是变为在整个程序生命期里面都有效 下面从汇编语言看其原理. 下面是c++源代码: void add() { static int i = 1; i++; } int main() { add(); } 下面是main对应的汇编码 复制代码 代码如下: ; 5 : int main() { push ebp mov ebp, esp ; 6 : add(); call [email protected]@YAXXZ ; 调用add ; 7 :

  • 从汇编看c++的默认析构函数的使用详解 2015-02-22

    本篇文章是对c++中默认析构函数的使用进行了详细的分析介绍.需要的朋友参考下 c++中,如果没有为一个类提供析构函数,那么编译器会为这个类提供默认的析构的函数.由于析构函数的功能和构造函数相反,因此和默认的构造函数类似,编译器也会提供无用的默认的析构函数,和非无用的析构函数.两者的分析情况一样(对于默认的构造函数分析,请参看<从汇编看c++中默认构造函数的使用分析>).并且编译器会提供非无用的默认析构函数情形和默认构造函数类似: 1 类含有虚成员函数(类继承自虚基类或者继承的基类含有虚成员函数

  • C++中的引用与指针的区别 2015-03-27

    指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一个内存地址,编译器不能通过该指针所指向对象的类型和大小,因此想要通过void*指针操作对象必须进行类型转化.(乱入了...) ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址: 引用是某块内存的别名. ★ 区别: 1. 指针是一个实体,而引用仅是个别名: 2. 引用使用时无需解引用(*),指针需要解引用: 3. 引用只能在定义时被初始化

  • 深入分析C语言中结构体指针的定义与引用详解 2014-08-10

    本篇文章是对C语言中结构体指针的定义与引用进行了详细的分析介绍,需要的朋友参考下 指向结构体类型变量的使用首先让我们定义结构体: struct stu { char name[20]; long number; float score[4]; } ; 再定义指向结构体类型变量的指针变量: struct stu *p1, *p2 ; 定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员: [例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出.

  • PHP中变量引用与变量销毁机制分析 2014-05-19

    这篇文章主要介绍了PHP中变量引用与变量销毁机制,较为深入的分析了PHP中变量的引用机制及其原理以及对应的变量的销毁机制,有助于深入理解PHP程序设计原理,需要的朋友可以参考下 本文实例分析了PHP中变量引用与变量销毁机制.分享给大家供大家参考.具体分析如下: 变量是php中一个非常重要的类型了,我们的有数据都通过变量或常量来进行操作,下文来看看变量引用与变量销毁. 在php中,符号"&"表示引用. 1.看看不引用的情况是这样子: $a = "hello world&

  • php中引用符号(&)的使用详解 2014-12-19

    php的引用就是在变量或者函数.对象等前面加上&符号,在PHP 中引用的意思是:不同的名字访问同一个变量内容,下面介绍如何使用PHP的引用 与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址变量的引用. PHP 的引用允许你用两个变量来指向同一个内容 $a="ABC"; $b =&$a; echo $a;//这里输出:ABC echo $b;//这里输出:ABC $b="EFG"; echo $a;//这里$a的值变为

  • 详解Javascript 中的this指针 2014-10-14

    前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的设计模式来实现面向对象的编程,其中this "指针"就是实现面向对象的一个很重要的特性.但是this也是Javascript中一个非常容易理解错,进而用错的特性.特别是对于接触静态语言比较久了的同志来说更是如此. 示例说明 我们先来看一个最简单的示例: <script type="text/javascript&q

  • c++引用和指针的实现 2013-04-17

    引用和指针有什么区别?引用在进程中是否会分配内存? C++ primer中说: 引用就是对象的另一个名字. C++ primer中说: 指针用于指向对象,保存的是另一个对象的地址. 从字面意义上,感觉引用并没有分配内存,而指针是分配了内存的,于是写了个小程序进行测试. #include <stdio.h> int main() { long val = 1; long &r_val = val; const long &const_r_val = val; const long

  • C++中引用的使用总结 2014-04-27

    以下是对C++中引用的使用进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 1引用的定义 引用时C++对C的一个重要的扩充,引用的作用是给变量起一个别名. 例如: int a; int &b=a;//声明b是a的引用 经过以上的声明,b就成为了a的别名,a和b的地位以及作用都是一样的. 将b声明为a的引用,不需要再为b开辟新的单元,b和a在内存中占同一存储单元,它们具有相同的地址. #include<iostream> using namespace std; int

  • C语言中函数与指针的应用总结 2014-05-10

    本篇文章是对C语言中函数与指针的应用进行了详细的分析介绍,需要的朋友参考下 1. 首先,在C语言中函数是一种function-to-pointer的方式,即对于一个函数,会将其自动转换成指针的类型. #include<stdio.h> void fun() { } int main(void) { printf("%p %p %p\n", &fun, fun, *fun); return 0; } ----------------------------------

  • C++中引用(&)的用法与应用实例分析 2014-06-03

    引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确.灵活地使用引用,可以使程序简洁.高效.故在本篇中我将对引用进行详细讨论,希望对大家更好地理解和使用引用起到抛砖引玉的作用 对于习惯使用C进行开发的朋友们,在看到c++中出现的&符号,可能会犯迷糊,因为在C语言中这个符号表示了取地址符,但是在C++中它却有着不同的用途,掌握C++的&符号,是提高代码执行效率和增强代码质量的一个很好的办法. 引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确.灵活地使用引用,可

  • C++中的对象指针总结 2014-07-13

    以下是对C++中的对象指针进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 指向对象的指针在建立对象的时候,变异系统会给每一个对象分配一定的存储空间,以存放其成员. 对象空间的起始地址就是对象的指针.可以定义一个指针变量,用来存放对象的指针. 一个简单的示例1.1: #include<iostream> using namespace std; class Student { public: int num; int score; Student(int ,int );//声

  • 从汇编看c++函数的默认参数的使用说明 2014-11-22

    本篇文章介绍了,在c++中函数的默认参数的使用说明分析.需要的朋友参考下 在c++中,可以为函数提供默认参数,这样,在调用函数的时候,如果不提供参数,编译器将为函数提供参数的默认值.下面从汇编看其原理. 下面是c++源码: int add(int a = 1, int b = 2) {//参数a b有默认值 return a + b; } int main() { int c= add();//不提供参数 } 下面是mian函数里面的汇编码: 复制代码 代码如下: ; 4 : int main(