引用是包装过的指针

从语义上理解,引用就是变量的别名,指针是一个变量,保存着变量的地址

因为引用是别名,所以引用不能单独存在,没有空引用,而能有空指针

但作为C++程序员,只从这个层面理解引用显然心里会发虚

因此上测试代码

#include <iostream>

void t1() {
    char c = ‘a‘;
    char &r = c;
    char *p = &c;

    r = ‘b‘;
    *p = ‘c‘;

    int size;

    size = sizeof(r);//1
    size = sizeof(p);//1

    char *q1;
    q1 = &r;

    char **q2;
    q2 = &p;
}

#pragma pack(1)
struct T2A {
    char &_r;
    char _c;
};
#pragma pack()

void t2() {
    char c = ‘a‘;
    T2A s1{ c, ‘b‘ };

    void *p;
    p = &s1;
    p = &s1._r;
    p = &s1._c;

    int size;
    size = sizeof(s1);//size值是5
}

void main() {
    t1();
    t2();

    system("pause");
}

代码本身没什么意思,有意思的是反汇编的结果

t1的反汇编

    char c = ‘a‘;
00F61728  mov         byte ptr [c],61h
    char &r = c;
00F6172C  lea         eax,[c]00F6172F  mov         dword ptr [r],eax  //引用r实际上是一个dword ptr类型
    char *p = &c;
00F61732  lea         eax,[c]
00F61735  mov         dword ptr [p],eax  //指针p看起来是不是和引用r在内存布局上一模一样?

    r = ‘b‘;
00F61738  mov         eax,dword ptr [r]
00F6173B  mov         byte ptr [eax],62h
    *p = ‘c‘;
00F6173E  mov         eax,dword ptr [p]
00F61741  mov         byte ptr [eax],63h  //赋值操作,引用和指针也是一模一样

    int size;

    size = sizeof(r);
00F61744  mov         dword ptr [size],1  //但引用是一个语法糖,对引用操作的时候,编译器会把它换成被引用的对象
    size = sizeof(p);
00F6174B  mov         dword ptr [size],4  

    char *q1;
    q1 = &r;
00F61752  mov         eax,dword ptr [r]  //取不到引用的地址,编译器给的是被引用对象的地址
00F61755  mov         dword ptr [q1],eax  

    char **q2;
    q2 = &p;
00F61758  lea         eax,[p]
00F6175B  mov         dword ptr [q2],eax  

t2反汇编

    char c = ‘a‘;
00F640C8  mov         byte ptr [c],61h
    T2A s1{ c, ‘b‘ };
00F640CC  lea         eax,[c] //取c的地址
00F640CF  mov         dword ptr [s1],eax  //s1的地址就是s1._r的地址,引用变量保存的是被引用对象的地址
00F640D2  mov         byte ptr [ebp-18h],62h  //ebp-18h是s1._c的地址

    void *p;
    p = &s1;
00F640D6  lea         eax,[s1] //取s1地址
00F640D9  mov         dword ptr [p],eax
    p = &s1._r;
00F640DC  mov         eax,dword ptr [s1]  //引用语法糖,想取s1._r的地址,实际上取到的是被引用对象c的地址
00F640DF  mov         dword ptr [p],eax
    p = &s1._c;
00F640E2  lea         eax,[ebp-18h]
00F640E5  mov         dword ptr [p],eax  

    int size;
    size = sizeof(s1);
00F640E8  mov         dword ptr [size],5  //引用变量_r 4字节,字符变量_c 1字节

由此可见,引用实际上是加了使用规则的指针

时间: 2024-10-24 05:47:25

引用是包装过的指针的相关文章

《C++ Primer》学习 之 返回数组的引用(返回数组的指针,方法与之相同)

/* 返回数组的引用(返回数组的指针,方法与之相同) 共四种方法(在下面示例程序中,调用其中一种方法时,需要将其他三种方法注释掉)*/ 1 #define _CRT_SECURE_NO_WARNINGS 2 #define HOME 3 #include <iostream> 4 #include <stdexcept> 5 #include <ctype.h> 6 #include <locale> 7 #include <iterator>

指针和引用(4)指向指针的指针

1.知识点 (1)在程序中可以声明指向任何数据类型的指针,指针也可以指向指针类型,成为指向指针的指针.下面是一个使用例子 1 int a=10,b=20; 2 int *q=&a; 3 int **p=&q; 4 **p=30; (2)如果想通过指针在被调函数中修改主调函数的变量,必须将主调函变量(务必确定该变量的类型,有时候可能变量本身就是指针,这时候形参就需要是指针的指针了)的地址作为参数,在被调函数中修改主调函数指向的内容. 2.面试题 2.1指针作为参数的常见错误 1 int fi

指针和引用(5)函数指针

1.知识点 (1)指针可以指向任何类型,也可以指向函数.每个函数在内存中都占用一段存储单元,这段存储单元的首地址称为函数的入口地址,指向之歌函数入口地址的指针称为函数指针. (2)函数基本用法如下: 1 int max(int a, int b) { 2 return a > b ? a : b; 3 } 4 int (*p)(int, int) = max;//定义函数指针时必须指明函数返回的类型和参数列表 5 int x = 10, y = 20; 6 int z = p(x, y);//可

c++/java/c# 几种编程语言的指针、引用比较

前一段时间,我在 cnblogs 别人的博客中,谈到: java 中的引用/指针,与 c++/C# 中的引用/指针不是一个概念. Java 引用,相当于 c++ 指针(fun3).Java 引用可以赋值 null, 而 c++ 引用 (见 fun2) 不能赋值 null,c++ 指针可以赋值 null(fun3). Java 中,无 c++ 引用(fun2)对应的语法. 结果引起不必要的质疑,特此,写博客,对c++/java/c# 几种编程语言的指针.引用,进行比较,期望引起更多的人,对此有所关

C++学习笔记----2.4 C++引用在本质上是什么,它和指针到底有什么区别

从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量). 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值.值传递过程中,被调

c++指针与引用问题

本来是回答问题的,到这里做个笔记 *&L是指针的引用,实参是个指针.所以L是实参指针的别名,对别名L的修改,等于对实参的修改.*L是传值,你无法改变传过来的实参指针变量的值程序代码: #include<iostream>using namespace std;void foo(int*p);int main(){    int a=5;    int *b=&a;    printf("%d %d\n",b,*b);    foo(b);    printf

(C/C++)区别:数组与指针,指针与引用

1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存.指针远比数组灵活,但也更危险. 数组和指针特点的简单比较: 数组 指针 保存数据 保存地址 直接访问数据 间接访问数据,先取得指针的内容,然后以它为地址取得数据 用于存储数目固定且类型相同的数据 通常用于动态数据结构 编译器自动分配和删除

值传递,指针传递;引用传递(c++独有)本质

要理解值传递.指针传递和引用传递的区别,主要要理解函数的实参和形参,函数的作用域(自动变量.栈),内存的布局以及指针和引用的特点.这里主要总结三种参数传递方式使用的主要场合. 值传递:只给函数提供输入值,需要复制开销,大对象很少使用值传递. 指针传递:可以改变指针指向内容的值,但是不能改变指针本身,无需复制开销.如果需要改变指针本身,可以使用二重指针或者指针引用. 引用传递:除了提供输入值外,还返回操作结果,无需复制开销. #include<stdlib.h> //值传递,函数体内变量n是参数

引用和指针的比较

以下内容摘抄自:高质量程序设计指南:C++C语言(第三版) 林锐 P152 引用符号:“&” 在此并非取地址的意思. int m; int& n=m; n是变量m的一个引用(Reference),m是被引用物(Referent). n相当于m的别名,对n的任何操作都是对m的操作.所以n既不是m的拷贝,也不是指向m的指针,其实n就是m自己. 引用的特性及其与指针的比较如下: 1.引用在创建的同时必须初始化,即引用到一个有效的对象.而指针在定义的时候不必初始化,可以在定义的任何地方重新赋值.