1、int

int 是 C++关键字,表示整型,其大小是 32 位有符号整型,表示的范围是 [-2,147,483,648 , 2,147,483,647];在声明和定义变量时使用,它表示的意思是所声明或所定义的变量为整型变量。

如果 int 用作函数参数时,其传递方向为值传递,即只能将实参的值传递给形参,而不能将形参的值传递给实参。

例如:通过这种方式去进行交换两个数是无法达到目的的。

#include<iostream>
using namespace std;

void swap1(int a,int b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int a = 1;
    int b = 2;
    swap1(a, b);
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}
// 结果为:a=1 b=2

可以看到,函数并没有实现 a, b 值的交换,因为传递的方式为值传递(单向传递)。

2、int&

这里的 & 不是取地址符号,而是引用符号,引用是 C++ 对 C 的一个重要补充, 变量的引用就是变量的别名。

如果变量 b 是变量 a 的引用,那么无论 a ,b 中任何一个值改变,另外一个也相应的改变。在声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。

注意:由于引用不是独立的变量,编译系统不给它单独分配存储单元,因此在建立引用时只有声明没有定义,只是声明它与原有的某一变量的关系。在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变量的别名。所以在C++中一个引用变量只能对应一个原始的变量,不能对应两个或多个原始的变量。

引用:

  • 声明引用时必须指定它代表的是哪一个变量,即对它初始化。

    • int &a = b; 这样是声明a是变量b的引用
    • int &a; 这样就是错的,没有指定a代表哪一个变量。
  • 引用与其所代表的变量共享同一内存单元,系统并不为引用另外分配存储单元。

    • 对于 int &a=b; 这个例子来说,要输出 a 和 b 的地址,肯定是相同的。
  • 怎样区分&是引用还是取地址符呢?

    • 方法是:判断&a这样的形式前是否有类型符即:int &a=b; 如果有类型符(int)则是引用,否则是取地址运算符。
  • 对引用的初始化,可以是一个变量名,也可以是另一个引用。
  • 引用初始化后不能再被重新声明为另一变量的别名。

    • 即一个别名只能对应一个原始变量,但是一个原始变量可以有多个别名,而且别名也可以由自己的别名。

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

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

  • 如果使用引用,则不必在swap函数设立指针变量,指针变量要另外开辟内存单元,其内容是地址。而引用不是一个独立的变量,并不占用内存单元。
  • 在main函数中调用swap函数时实参不必再变量名前加&以表示地址,系统传递的是实参的地址不是实参的值。
  • 使用指针变量时,为了表示指针变量所指向的变量,必须使用指针运算符 *,而使用引用时,引用就代表该变量,不必使用指针运算符*。
  • 用引用完成的工作,用指针也能完成。但引用比指针的使用直观、方便,直截了当,不必“兜圈子”,容易理解。有些过去只能用指针来处理的问题,现在可以用引用来代替,从而降低了程序设计的难度。

对引用进一步说明:

  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,错误。因为引用不是一种独立的数据类型,因此不能建立指向引用类型的指针变量。

  1. 可以建立指针变量的引用如:
int i = 5;
int *p = &i;
int * &pt = p;  //建立指针变量p的引用pt

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

  1. 可以用 const 对引用加以限定,不允许直接改变该引用的值,但是可以改变原变量的值去改变引用的值;
int i = 5;
const int &a = i;
a = 3;  //错误,因为引用 a 是 const int 类型不能直接改变引用的值

但是可以这样修改:

i = 3;  // 此时输出 i 和 a 都是 3
  1. 可以用常量或表达式对引用进行初始化,但此时必须用 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 的原因。

#include<iostream>
using namespace std;

int main() {
    int a = 10;
    int *p = &a;
    cout << "a 的地址 = " << &a << endl;
    cout << "p 的地址 = " << p << endl;
    cout << "*p 取*p里面的内容 = " << *p << endl;
    cout << "&p 存放地址p的地址 = " << &p << endl;
    cout << "*(&p) 存放地址p的地址里面的内容 = " << *(&p) << endl;
    return 0;
}

结果:

a 的地址 = 0x61fe1c
p 的地址 = 0x61fe1c
*p 取*p里面的内容 = 10
&p 存放地址p的地址 = 0x61fe10
*(&p) 存放地址p的地址里面的内容 = 0x61fe1c

Last modification:August 11, 2021
如果觉得我的文章对你有用,请随意赞赏