前言
看了网上的一些文章,我想大家在学习引用的时候总是容易把引用理解为变量的别名,这其实是错误的。引用实际上是给一个对象起别名,相当于给一个同类型的对象起别名,更严谨的来说上应该是相当于给对象/变量所在的内存空间起别名。
基本概念
在C++中可以定义“引用”。定义方式如下:
语法:数据类型 &别名 = 同类型的某对象或变量名
作用:定义了一个某种类型的引用,并将其初始化为引用某个同类型的对象。相当于给一个同类型的对象起别名,更严谨的来说上应该是相当于给对象/变量所在的内存空间起别名。
代码:
#include "stdlib.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a=10;
int &b=a;
cout <<"Loc(a):"<<&a<<endl;
cout <<"Loc(b):"<<&b<<endl;
system("pause");
return 0;
}
输出:
Loc(a):0x61fe14
Loc(b):0x61fe14
请按任意键继续. . .
注意:网上很多人认为,被引用的只能是变量,这种说法,笔者认为是不严谨的。看下面这种情况:
int *p=new int(2);
int &c=*p;
cout <<"Loc(c):"<<&c<<endl;
cout <<"c:"<<c<<endl;
c=11;
cout <<"p:"<<*p<<endl;
*p=12;
cout <<"c:"<<c<<endl;
cout <<"p:"<<*p<<endl;
为引用变量初始化的右值*p是变量吗?显然不是吧,这段代码是可以正常输出的。结果如下:
Loc(c):0x24d2430
c:2
p:11
c:12
p:12
这样或许还是不太明显,那么来看看这个:
int &c=new int(2);
右值替换为 new int(2) ,得到的结果依然是正确的。
最终我们可以得出引用变量是定义了一个某种类型的引用,并将其初始化为引用某个同类型的对象。
引用特性
- 定义引用时,只能使用同类型对象去初始化引用
引用相当于为一个变量“取别名”,也就要求了被引用的必须为一个同类型的对象。 - 一旦初始化后,引用了一个对象将无法引用其他对象。
定义引用时初始值会与引用进行绑定,故引用一旦引用一个对象将无法引用其他对象,因为对引用的赋值实际上是对被引用对象的赋值,通过下面代码可证明:
int a=10; int &b=a; int p=2; int &c=p; c=a; cout<<c<<endl; cout<<p<<endl;
输出结果:
10 10
- 一个变量可有多个引用
引用变量占空间吗
这里先问大家一个问题:我们知道值类型的变量是不占内存的,那么引用变量它占内存吗?
网上的答案众说纷纭,笔者查阅了一些有详细论证的文章,可以先告诉大家一个结论:引用变量它是占内存空间,所占内存空间就是引用所引用的对象的地址,故占用的内存空间的大小和指针类型的大小是相同的,在32位系统中会占4个字节。
通过几篇文章中给出的反汇编代码,我们可以发现在引用变量初始化那段代码会出现两行汇编代码
lea eax,[var]
move dword ptr [refVar],eax
笔者对这两段汇编代码的大概理解: 检查var变量是否在寄存器中,再把寄存器中的var的地址赋给以refVar为地址的一块内存区域。从上面汇编代码可以看出,这两行汇编代码跟指针的汇编代码是完全一致的,虽然引用是一个对象的别名,但是在汇编层面,和指针是一样的。
参考文章:C++的那些事:你真的了解引用吗
2022/11/8 0:25
2022/11/8 :21:10
引用的本质
前面通过汇编语言我们了解到,引用在C++内部实现是一个指针。
为了进一步证明,我百度查了一下关键字“引用的本质是什么?”。结果真的令我张目结舌,看看吧。
有说常量指针的,有说指针常量的。我真的会谢!我已经数不清几次吐槽现在的互联网文章了,一个错的..一堆引用 复制粘贴..。
首先说明这两个概念是完全不一样的,今天就以我对引用的理解,把这个概念跟大家说清楚吧。
我们知道引用变量一旦引用一个对象将无法引用其他对象,因为对引用的赋值实际上是对被引用对象的赋值。那这个不就是很明显吗?
笔者之前写过指针的文章,分别介绍过了常量指针与指针常量,这里再介绍一下。
- const修饰指针 --- 常量指针
const修饰*p 表示通过指针所指的值是常量,指针的指向可以修改,指针指向的值不可修改 - const修饰常量 --- 指针常量
const修饰p,表示指针是常量,指针的指向不可以改,通过指针指向的值可以改。
那引用变量概念不就很明显跟指针常量概念一样吗?为什么网上能说成常量指针?麻烦各位CSDN大佬们,在你们撰写专业名词、概念相关的内容能好好认真的查阅一下吗?
关于 常量指针与指针常量 详细证明过程见文章 C++语言入门-指针 - 麦瑞克博客 (unitymake.com)
编译器内部操作
int &ref=a;
ref=20;
当C++内部发现ref:引用变量
是引用类型时,会自动帮我们进行解引用的操作 *ref=20;
引用变量作形参
示例-交换值:
void SwapNumByReference(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
引用形参与指针形参类似,我觉得应该没什么需要特别指出,就不赘述了,对这块不清楚的可以先去看下我之前那几篇指针的文章:
C++基础入门 - 值传递与引用参数|指针与函数 - 麦瑞克博客 (unitymake.com)
引用变量作返回值
与指针当返回值类似,引用变量作返回值也有以下规则。详细证明见指针 C++语言入门-指针
注意:
- 不要返回局部变量的引用;
- C++支持函数调用返回作为左值作赋值操作;
引用变量作常量
作用:防止引用变量所引用的值被修改,主要用来修饰形参。
禁止引用形参修改值:
代码下载
本文所有案例代码文件:
2022/11/9 0:23