C++中 引用符&,以int&举例说明

本文详细解释了C++中int和int&的区别,包括它们的基本概念、如何使用以及在函数参数中的作用。并通过实例对比了引用与指针的使用方式,帮助读者更好地理解和掌握C++中的引用机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇是摘抄自byteH的一篇,感觉有用,摘抄过来了,做了一些修改。

1、int;
int是C++关键字,表示整型,其大小是32位有符号整型,表示的范围是-2,147,483,648 到2,147,483,647;在声明和定义变量时使用,它表示的意思是所声明或所定义的变量为整型变量。
如果其用于函数参数时,其传递方向为值传递,即只能将实参的值传递给形参,而不能将形参的值传递给实参。
例如:通过这种方式去进行交换两个数是无法达到目的的。
例子1:

#include<iostream>
using namespace std;
voidswap1(inta,intb)
{
inttmp;
tmp = a;
a = b;
b = tmp;
}
int main(){
inta = 1;
intb = 2;
swap1(a, b);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
system("pause");
return0;
}

结果为:
a=1
b=2
因为传递的方式为值传递(单向传递);

2、int&;
这里的&不是取地址符号,而是引用符号,引用是C++对C的一个重要补充。变量的引用就是变量的别名,讲的通俗一点就是另外一个名字,比如:“张三这个人在家里,老爸老妈叫他三娃子,那么这个三娃子就是指张三这个人,如果叫张三去做某事,就是叫三娃子去做某事,这两个名字指的是同一个人。”同样可以理解如果变量b是变量a的引用 那么无论a,b中任何一个值改变,另外一个也相应的改变,在声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。请注意:由于引用不是独立的变量,编译系统不给它单独分配存储单元,因此在建立引用时只有声明没有定义,只是声明它与原有的某一变量的关系

在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变量的别名。说得简单点:张三和三娃子是指同一个人,不能李四也叫三娃子,如果可以这样,叫三娃子去做什么,是叫李四呢还是张三呢,这就会乱套了。所以在C++中一个引用变量只能对应一个原始的变量,不能对应两个或多个原始的变量;

下面简单说明引用:

a)声明引用时必须指定它代表的是哪一个变量,即对它初始化。
int &a=b;这样是声明a是变量b的引用。
如果是int &a;这样就是错的,没有指定a代表哪一个变量。

b)引用与其所代表的变量共享同一内存单元,系统并不为引用另外分配存储单元;
这个应该好理解;就像前面所说的,张三和三娃子都是同一个人,三娃子只是张三的别名。
因此,对于 int &a=b;这个例子来说,要输出a和b 的地址,肯定是相同的。

c)怎样区分&是引用还是取地址符呢?方法是:判断&a这样的形式前是否有类型符即
int &a=b;如果有类型符(int)则是引用,否则是取地址运算符。

d)对引用的初始化,可以是一个变量名,也可以是另一个引用。
换句话说:张三的别名可以是三娃子,三小子……及其他多个别名
而三娃子也可以有其他的别名,比如说:老三,小三等
用程序可以这样:


int a=1; //这里是定义一个整型变量
int &b=a;//声明b是整型变量a的别名
int &c=b;//声明c是整型引用变量b的别名
int &d=a;//声明d是整型变量a的别名

e)引用初始化后不能再被重新声明为另一变量的别名
即三娃子既然是指张三这个人,就不能让其他人也叫三娃子
即一个别名只能对应一个原始变量,但是一个原始变量可以有多个别名,而且别名也可以由自己的别名。

C++中增加引用主要是作为函数参数,进行数据传递的功能;

我们知道如果用变量名作为实参,其传递方向是单向的,而用引用作为实参其传递方向是双向的;
也许你会问,在c语言中不是有指针吗,用指针进行参数传递不也是双向的吗?其实其本质上也是值传递,只不过是将变量的地址传给指针,通过指针获取变量的值,这样做虽能得到结果,但通过指针运算符去访问有关变量,比较麻烦。

下面分析一下使用引用和使用指针变量作为函数形参的不同(以例子1中的swap函数为例):

1、如果使用引用,则不必在swap函数设立指针变量,指针变量要另外开辟内存单元,其内容是地址。而引用不是一个独立的变量,并不占用内存单元

2、在main函数中调用swap函数时实参不必再变量名前加&以表示地址,系统传递的是实参的地址不是实参的值。

3、使用指针变量时,为了表示指针变量所指向的变量,必须使用指针运算符,而使用引用时,引用就代表该变量,不必使用指针运算符

4、用引用完成的工作,用指针也能完成。但引用比指针的使用直观、方便,直截了当,不必“兜圈子”,容易理解。有些过去只能用指针来处理的问题,现在可以用引用来代替,从而降低了程序设计的难度。

对引用进一步说明:

1、不能建立void类型的引用
因为任何实际存在的变量都是属于非void类型的,void的含义是无类型或空类型,void只是在语法上相当于一个类型而已。

2、不能建立引用的数组
如:char c[6]=”hello”;
char &rc=c;//错误
因为数组名是数组首元素的地址,本身不是一个占有存储空间的变量。

3、可以将变量的引用的地址赋给一个指针,此时指针指向的是原来的变量。
这句话可以这样说:将引用变量的地址赋给一个指针,此时指针指向的是引用变量,相当于指向原来的变量

int a=2;
int &b=a;//这个声明语句中的&是一个引用
int *p=&b;//这个指针初始化语句中的&是取地址运算符
上面一行等价于 int *p=&a;
但是不能定义指向引用类型的指针变量,不能写成int & *p=&a;//企图定义指向引用类型的指针变量p,错误。
因为引用不是一种独立的数据类型,因此不能建立指向引用类型的指针变量

4、可以建立指针变量的引用如

int i=5;
int *p=&i;
int * &pt=p;//建立指针变量p的引用pt

引用变量pt代表一个int *类型的数据对象(即指针变量)

5、可以用const对引用加以限定,不允许改变该引用的值,但是可以改变原
变量的值去改变引用的值;也就是说不能通过改变引用的值达到给边原变量的目的,但是原变量的自身操作是没影响的。一般用在一些自定义的类型传入一些功能函数中时,这种功能函数一般只是读出类型对象的一些信息,而不需要改变,所以对引用参数加上个const,防止误修改。

int i=5;
const int &a=i;
a=3;//错误,因为引用a是const int 类型不能直接改变引用的值

但是可以这样修改:

i=3;

此时输出i和a都是3

6、可以用常量或表达式对引用进行初始化,但此时必须用const作声明

int i=5;
const int &a=i+1;

此时编译系统是这样处理的:生成一个临时变量,用来存放该表达式的值,引用是
该临时变量的别名、系统将

const int &a=i+1;

转换为:

int temp=i+1;
const int &a=temp;

临时变量是在内部实现的,用户不能访问临时变量;
用这种办法不仅可以用表达式对引用进行初始化,还可以用不同类型的变量对之初始化;如

double d=3.1415926;
const int &a=d;

以上等价为:

double d=3.1415926;
int temp=d;//用中间变量进行过渡
const int &a=temp;

如果在上面不用const则会发生错误:

double d=3.1415926;
int &a=d;//未加const,错误

为什么?因为如果可以这样做,那么修改引用a的值(如a=3.56),则临时变量temp的值也变为3.56,即修改了临时变量temp的值,但不能修改变量d的值,这往往不是用户所希望的,即存在二义性。与其允许修改引用的值而不能实现用户的目的,还不如不允许修改引用的值。这就是C++规定对这类引用必须加const的原因。

&lt;think&gt;好的,我现在需要解释C++中的&amp;和*号。首先,我得回忆一下这两个号的不同用法,可能用户容易混淆它们,特别是对于新手来说。 首先,&amp;在C++中有几个用途。一个是作为取地址运算,比如int a; int* ptr = &amp;a; 这里&amp;用来获取变量a的内存地址。另一个是作为引用声明,比如void func(int&amp; ref) {...},这里的引用ref是变量的别名,修改ref会影响原变量。还有在按位与操作中,比如a &amp; b,但用户的问题可能更关注指针和引用相关的用法。 然后是*号,它也有多种用途。作为指针声明,比如int* ptr;,这里ptr是一个指向int的指针。解引用运算,比如*ptr = 5;,这里*用来访问指针指向的内存。还有在乘法运算中,但同样用户可能关注指针相关的内容。 接下来需要分清楚什么时候&amp;是取地址,什么时候是引用。同样,*在声明和解引用时的区别。可能需要举例说明,比如声明指针变量和使用指针访问值的不同。引用的例子,比如函数参数中的引用传递,说明引用必须在声明时初始化,而指针可以为空。 还要注意在C++11之后出现的右值引用,比如int&amp;&amp;,但可能用户的问题不涉及这么深,暂时先不提。重点是比较指针和引用的区别,比如指针可以重新指向其他变量,而引用一旦绑定就不能改变,引用更安全但灵活性较低。 需要指出在函数参数传递中,使用引用可以避免拷贝,提高效率,尤其是const引用。而指针参数需要处理可能的空指针问题,引用则不需要,因为必须绑定有效对象。 可能用户还会混淆指针和引用语法,比如在函数调用时,指针需要显式取地址,而引用则直接传递变量。例如,func(&amp;a)如果参数是指针,而func(a)如果参数是引用。 需要确保例子准确,比如: int a = 10; int* ptr = &amp;a; // &amp;作为取地址 int&amp; ref = a; // &amp;作为引用声明 *ptr = 20; // *作为解引用 ref = 30; // 修改引用相当于修改a 然后说明指针可以指向nullptr,而引用不能为空,必须初始化。指针可以重新赋值,引用不能重新绑定。 可能还需要提到在类型声明中,int*和int&amp;的不同,以及指针的算术运算,但用户的问题可能不涉及这些细节。 总结时,分点列出两者的不同用途,确保结构清晰。可能还需要提醒常见的错误,比如未初始化的指针或引用,或者混淆解引用和取地址操作。 最后检查是否有语法错误,比如LaTeX格式是否正确,使用$包围数学表达式,但C++代码不需要LaTeX,所以可能不需要。不过用户提到的系统级指令中关于数学表达式使用$,但代码部分可能不需要,所以保持代码块的正确格式即可。确保回答合用户要求的结构,逐步解释,正确可靠。&lt;/think&gt;在 C++ 中,`&amp;` 和 `*` 是两种重要的运算,主要用于 **指针** 和 **引用** 的操作。以下是逐步解释: --- ### 一、`&amp;` 的用途 #### 1. **取地址运算** - 作用:获取变量的内存地址。 - 示例: ```cpp int a = 10; int* ptr = &amp;a; // ptr 存储变量 a 的地址 ``` - 此时 `&amp;a` 返回 `a` 的地址(如 `0x7ffd42c`)。 #### 2. **声明引用** - 作用:定义一个变量的别名(引用),必须初始化且不可重新绑定。 - 示例: ```cpp int a = 10; int&amp; ref = a; // ref 是 a 的别名 ref = 20; // 修改 ref 等价于修改 a ``` - 引用本质是&ldquo;安全指针&rdquo;,但语法更简洁。 --- ### 二、`*` 的用途 #### 1. **声明指针** - 作用:定义一个指向某种类型的指针变量。 - 示例: ```cpp int a = 10; int* ptr = &amp;a; // ptr 是指向 int 的指针 ``` #### 2. **解引用运算** - 作用:访问指针指向的内存值。 - 示例: ```cpp int a = 10; int* ptr = &amp;a; *ptr = 20; // 通过指针修改 a 的值 ``` - 此时 `*ptr` 等价于直接操作 `a`。 --- ### 三、对比与注意事项 | 特性 | 指针 (`*`) | 引用 (`&amp;`) | |--------------------|-------------------------------------|-------------------------------------| | **初始化** | 可指向 `nullptr` 或未初始化 | 必须初始化,不可为空 | | **重新绑定** | 可以修改指向其他地址 | 一旦绑定,不可更改 | | **内存操作** | 显式操作地址(需 `*` 解引用) | 隐式操作,直接使用变量名 | | **安全性** | 需处理空指针和悬垂指针 | 更安全(无空引用) | --- ### 四、示例代码 ```cpp #include &lt;iostream&gt; using namespace std; int main() { int a = 10; // 使用 &amp; 取地址,* 声明指针 int* ptr = &amp;a; // ptr 存储 a 的地址 *ptr = 20; // 通过指针修改 a 的值 // 使用 &amp; 声明引用 int&amp; ref = a; // ref 是 a 的别名 ref = 30; // 修改 ref 等价于修改 a cout &lt;&lt; a &lt;&lt; endl; // 输出 30 return 0; } ``` --- ### 五、常见用途 1. **指针**: - 动态内存分配(`new`/`delete`)。 - 传递函数参数(避免拷贝大对象)。 - 实现多态(基类指针指向派生类对象)。 2. **引用**: - 函数参数传递(如 `void swap(int&amp; x, int&amp; y)`)。 - 返回值优化(避免拷贝返回值)。 - 范围 for 循环(如 `for (auto&amp; num : list)`)。 --- ### 六、易错点 - **悬垂指针**:指针指向已释放的内存。 - **空指针解引用**:访问 `nullptr` 会导致崩溃。 - **引用未初始化**:如 `int&amp; ref;` 会编译报错。 理解 `&amp;` 和 `*` 的核心在于区分 **地址操作** 和 **别名绑定**,根据场景选择合适的方式。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值