指针

指针

什么是指针?

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var-name;Code language: JavaScript (javascript)

在这里,type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
double *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */Code language: JavaScript (javascript)
int a;
a = 1;
int b = 2;
int *c = &b; //c是指针 并不是*c 星c 
//&是取地址符 &b就是获取b的地址 赋值到c这个指针Code language: JavaScript (javascript)
#include <iostream>
using namespace std;

int main() {
	
	float a,b,c;
	cout << &a << endl;
	cout << &b << endl;
	int *_a;
	_a = &a;
	cout << _a << endl;
	
	return 0;
}Code language: PHP (php)

获取一个变量的地址 可以使用 & 例如

int a;
a = 123;
int *_zz = &a;Code language: HTML, XML (xml)
#include <iostream>
using namespace std;

int main() {
	
	int a;
	a = 123;
	int *_zz = &a;//变量的地址 只能使用相同类型的指针 例如这里的int指针 来存放 否则
	float *_ff = &a;//类型不一样会报错 
	
	return 0;
}Code language: PHP (php)

我们的例子

//指针也有数据类型 
int *_pc;
float *_pf;
double *_pd;
bool *_pb; 
//指针的类型之间有什么区别
//可能有些同学有疑问?
//明明说指针是存储地址 地址都是整数吧 虽然是十六进制
//正常来说 应该都是整数类型的指针来存储就行了
//指针的类型和里面存储内容的类型是不一样的
int age = 1;
float price = 1.2f;
// *c = &age; //使用指针的时候 如果放在是左边 也就是对它赋值 是使用不带*的
_pc = &age;
//_pf = &age; //不能使用int的地址存储到float的指针里面Code language: JavaScript (javascript)

取地址符

//取地址符 & 
int a = 1;
float f = 1.2f;
cout << &a << endl;
cout << &f << endl;Code language: JavaScript (javascript)
#include <iostream>
using namespace std;

int main() {
	
	int *ip;    //整型指针 
    int age;    //整型变量 
    age = 100;  //初始化变量
	ip = &age;  //把变量的地址存放给指针
	
	cout << "age:" << age <<endl; 
	cout << "&age:" << &age <<endl;  
	cout << "ip:" << ip <<endl;    //当不带星号的时候 就是获取指针中的地址 十六进制的数 
	cout << "*ip:" << *ip <<endl;  //这里是获取指针所指向地址的内存的值 要注意和指针定义的时候的区别 int *ip; 
	
	return 0;
}Code language: PHP (php)
#include <iostream>
using namespace std;

int main() {
	
	int age;
	int *_age;
	//*_age = &age;//出错 不能把地址赋给指针所指向的变量 
	_age = &age;//给指针的时候是这样使用
	*_age = 100;//给指针所指向的变量复制
	cout << age << endl;  //100
	age = 120; 
	cout << *_age << endl;//120
	
	return 0;
}Code language: PHP (php)

没有初始化的指针

#include <iostream>
using namespace std;

int main() {
	
	int *_zz;
	cout << _zz << endl;
	cout << *_zz << endl;
	
	return 0;
}Code language: PHP (php)

我们的代码

//取地址符 & 
int a = 1;
float f = 1.2f;
cout << &a << endl;
cout << &f << endl; 
int *_pa = &a;//声明和赋值一起 所以左边可以带* 
float *_pf = &f;
cout << a << endl; //普通的输出变量 
cout << *_pa << endl; //通过指针来读取它保存的地址的变量的值 
 //如果对于右值 *_pa是获取指向的变量的值 
 //对于指针 不同星号 就是地址 用星号就是通过地址取值
cout << _pa << endl; //输出指针的保存地址Code language: JavaScript (javascript)

左值右值

场景说明
声明的时候 *p 例子 int *p = &age;不存在非声明不带星号 p int *a; a = &age;
*p 取地址的变量的值 int *a = &age; cout << *a;读取的是 age 的值
不带星号 则是取指针保存地址 cout << a;输出 age 的地址

空指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。

赋为 NULL 值的指针被称为空指针。

NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:

#include <iostream>
using namespace std;

int main ()
{
   int  *ptr = NULL;
   cout << "ptr 的值是 " << ptr ;
   return 0;
}Code language: PHP (php)

当上面的代码被编译和执行时,它会产生下列结果:

ptr 的值是 0

在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

如需检查一个空指针,您可以使用 if 语句,如下所示:

if(ptr)     /* 如果 ptr 非空,则完成 */
if(!ptr)    /* 如果 ptr 为空,则完成 */Code language: JavaScript (javascript)

因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。

我们的程序

int  *ptr = NULL;
cout << "ptr 的值是 " << ptr ; //0 在C++ 0 是false
//我们可以通过它来进行空指针判断
if(ptr){
   cout << "prt不是空指针" << endl; 
} 
else{
   cout << "prt是空指针" << endl;
}Code language: PHP (php)

我们的代码

int *a = NULL;//NULL就是0 0是操作系统保护的 不会给人使用 
cout << a  << endl;
if(a) //控制着 NULL => 0  bool类型里面 => false 
{
   cout << "空指针" << endl;
}
else
{
   //不是空指针 
   cout << *a << endl; 
}Code language: PHP (php)

指针的算术运算

指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、–、+、-。

假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:

int *ptr;   // 保存的地址是1000
ptr++;Code language: JavaScript (javascript)

在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。

它经常应用到数组上面。

递增一个指针

我们喜欢在程序中使用指针代替数组,因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。下面的程序递增变量指针,以便顺序访问数组中的每一个元素:

int  ages[3] = { 10, 100, 200 };
int  *ptr;
int a = 12;
//ptr = &a; //普通的变量 通过取地址符获取地址 
//对于数组来说 直接数组名就可以
ptr = ages;//ages是第一个元素10的地址 
for(int i = 0;i<3;i++)
{
   //cout << ages[i] << endl;以前的写法
   cout << ptr << endl;
   cout << *ptr << endl;
   //移动到下一个位置
   ptr++; //++并不是+1 而是+4 为什么 因为每次它是增加一个格子 一个格子4个字节 
}
//0x70fe00
//0x70fe04
//0x70fe08Code language: JavaScript (javascript)
递减一个指针

同样地,对指针进行递减运算,即把值减去其数据类型的字节数,如下所示:

int  ages[3] = { 10, 100, 200 };
int  *ptr;
ptr = &ages[2];//获取最后一个元素的地址 
for(int i = 2;i>=0;i--)
{
   cout << ptr << endl;
   cout << *ptr << endl;
   ptr--;
}Code language: JavaScript (javascript)

获取最后一个元素的地址 和第一个元素的地址不一样。最后一个元素 需要 &,第一个元素 直接数组名就可以。

指针的比较

指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

下面的程序修改了上面的实例,只要变量指针所指向的地址小于或等于数组的最后一个元素的地址 &ages[2],则把变量指针进行递增:

int ages[3] = {1,2,3};
int *ptr = ages;
while(ptr <= &ages[2]) //只要少于等于最后一个元素的地址 则循环
{
   cout << *ptr << endl;
   ptr++; 
} 
cout << *ptr << endl;//超出了数组的范围 最后一个元素的下一个地址Code language: JavaScript (javascript)

指针与数组

指针和数组是密切相关的。事实上,指针和数组在很多情况下是可以互换的。

例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。请看下面的程序:

#include <iostream>
using namespace std;
const int MAX = 3;

int main ()
{
   int  var[MAX] = {10, 100, 200};
   int  *ptr;
 
   // 指针中的数组地址
   ptr = var;
   for (int i = 0; i < MAX; i++)
   {
      cout << "var[" << i << "]的内存地址为 ";
      cout << ptr << endl;
 
      cout << "var[" << i << "] 的值为 ";
      cout << *ptr << endl;
 
      // 移动到下一个位置
      ptr++;
   }
   return 0;
}Code language: PHP (php)

下面通过指针来修改数组的值。

#include <iostream>
using namespace std;
const int MAX = 3;

int main()
{
	int  var[MAX] = { 10, 100, 200 };

	for (int i = 0; i < MAX; i++)
	{
		*var = i;    // 这是正确的语法
		//var++;       // 这是不正确的
	}
	*(var + 2) = 500;
	for (int i = 0; i < MAX; i++)
	{
		cout << var[i] << endl;
	}
	return 0;
}Code language: PHP (php)

我们的代码

int ages[3] = {1,2,3}; 
int *prt = NULL;
//prt = &ages; //对于数组不能像普通变量那样使用 取地址符
prt = ages; //直接通过数组名 就是数组的地址

//以前的方式输出数组的元素
cout << "-------以前的写法" << endl; 
for(int i=0;i<3;i++)
{
   cout << ages[i] << endl;
} 

//通过指针的写法
cout << "通过指针的方式" << endl;
for(int i=0;i<3;i++)
{
   cout << "ages["<< i<<"]:" << prt << endl;		
   cout << "ages["<< i<<"]的值:" << *prt << endl;
   prt++;//让地址改变为下个元素的地址
} 

prt = ages;//让指针回到第一个元素 

//通过指针来修改元素
cout << "通过指针来修改元素" << endl;
for(int i=0;i<3;i++)
{
   *prt = i+10; //*prt是表示元素的值 
   //ages[i] = 10;
   prt++;//让地址改变为下个元素的地址
}  

prt = ages;
*(prt+2) = 500;

cout << "修改元素之后"<< endl;
for(int i=0;i<3;i++)
{
   cout << ages[i] << endl;
} 

int a = 1;
int *_a = &a; //以前的写法Code language: PHP (php)

指针运算符 * 应用到 var 上是完全可以的,但修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。

由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。例如,下面是一个有效的语句,把 var[2] 赋值为 500:

*(var + 2) = 500;Code language: JavaScript (javascript)

上面的语句是有效的,且能成功编译,因为 var 未改变。

int ages[3] = {1,2,3}; 
int *prt = NULL;
//prt = &ages; //对于数组不能像普通变量那样使用 取地址符
prt = ages; //直接通过数组名 就是数组的地址

*(prt+2) = 500;
for(int i=0;i<3;i++)
{
   cout << ages[i] << endl;
} 

for(int i=0;i<3;i++)
{
   ages++; //数组名是常量 不能改变的 
   prt = ages; 
   cout << *prt << endl;
}Code language: PHP (php)

ages 是一个地址,是第一个元素的地址,但是它是一个常量。我们如果要遍历,可以通过赋值给指针来进行遍历。

指针数组

在我们讲解指针数组的概念之前,先让我们来看一个实例,它用到了一个由 3 个整数组成的数组:

#include <iostream>
using namespace std;
const int MAX = 3;

int main()
{
	int  var[MAX] = { 10, 100, 200 };

	for (int i = 0; i < MAX; i++)
	{
		cout << "Value of var[" << i << "] = ";
		cout << var[i] << endl;
	}
	return 0;
}Code language: PHP (php)

可能有一种情况,我们想要让数组存储指向 int 或 char 或其他数据类型的指针。下面是一个指向整数的指针数组的声明:

int *ptr[MAX];Code language: CSS (css)

在这里,把 ptr 声明为一个数组,由 MAX 个整数指针组成。

因此,ptr 中的每个元素,都是一个指向 int 值的指针。

下面的实例用到了三个整数,它们将存储在一个指针数组中,如下所示:

#include <iostream>
using namespace std;
const int MAX = 3;

int main ()
{
   int  var[MAX] = {10, 100, 200};
   int *ptr[MAX];
 
   for (int i = 0; i < MAX; i++)
   {
      ptr[i] = &var[i]; // 赋值为整数的地址
   }
   for (int i = 0; i < MAX; i++)
   {
      cout << "Value of var[" << i << "] = ";
      cout << *ptr[i] << endl;
   }
   return 0;
}Code language: PHP (php)
#include <iostream>
using namespace std;
const int MAX = 3;

int main()
{
    int ages[MAX] = { 10, 100, 200 };
	for (int i = 0; i < MAX; i++)
	{
		cout << "Value of ages[" << i << "] = ";
		cout << ages[i] << endl;
	}
	//变量指针 
	int *p;
	int age = 123;
	p = &age;
	cout << *p << endl; 
	//指针数组 就是一个用来存储指针的数组
	int *prtages[MAX]; 
	for (int i = 0; i < MAX; i++)
	{
	  	prtages[i] = &ages[i];
	}

	cout << "遍历数组指针读取每个元素指向的变量的值" << endl; 
	for (int i = 0; i < MAX; i++)
	{
	   cout <<	*prtages[i] << endl;
	}	
     
    return 0;
}Code language: PHP (php)

您也可以用一个指向字符的指针数组来存储一个字符串列表,如下:

#include <iostream>
using namespace std;
const int MAX = 4;

int main()
{
	const char *names[MAX] = {
					  "Zara Ali",
					  "Hina Ali",
					  "Nuha Ali",
					  "Sara Ali",
	};

	for (int i = 0; i < MAX; i++)
	{
		cout << "Value of names[" << i << "] = ";
		cout << names[i] << endl;
	}
	return 0;
}Code language: PHP (php)

指向指针的指针

int **c 是一个指向指针的指针,它保存了另外一个指针的地址。它需要两个星号。

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。

当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针:

int **var;Code language: JavaScript (javascript)

当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,如下面实例所示:

#include <iostream>
using namespace std;

int main()
{
	int  var;
	int  *ptr;
	int  **pptr;

	var = 3000;

	// 获取 var 的地址
	ptr = &var;

	// 使用运算符 & 获取 ptr 的地址
	pptr = &ptr;

	// 使用 pptr 获取值
	cout << "var 值为 :" << var << endl;
	cout << "*ptr 值为:" << *ptr << endl;
	cout << "**pptr 值为:" << **pptr << endl;

	return 0;
}Code language: PHP (php)
int a = 1;
int *p = &a; //*p保存普通变量的地址 
//int **c = &*p; //非声明的时候 *p 表示是指向变量 &*p 等同&a 
//如果这样写 报错 因为**c 应该是保存指针的地址 
int *p2 = &*p;//这样写没问题 这样写其实有点多余 等于下面
int *p3 = p; 
cout << "a:" << a << endl;
cout << "*p:" << *p << endl;
cout << "*p2:" << *p2 << endl;
cout << "*p3:" << *p3 << endl;

//int **c = p; //这样写也是会报错 p是普通变量的地址 不是指针的地址 
int **c = &p; //对指针取地址符
cout << "**c:" << **c << endl;//通过指针的指针获取值 

int ***t = &c;//取c的地址
cout << "***t:" << ***t << endl;Code language: JavaScript (javascript)

指针作为函数参数

就是指针作为函数的参数。传递给函数内部使用。函数内部有了这个指针就可以操作指针指向的变量。

C++ 允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。

下面的实例中,我们传递一个无符号的 long 型指针给函数,并在函数内改变这个值:

#include <iostream>
using namespace std;

void getSeconds(int *par);

int main()
{
    int age = 40;
	getSeconds(&age); //把变量的地址付给函数 
	cout << age << endl; 
    return 0;
}

void getSeconds(int *par) 
{
	*par = 100;//把指针所指向的变量的值改为了100 就相当于修改了age的值 
	return;
}Code language: PHP (php)

能接受指针作为参数的函数,也能接受数组作为参数,如下所示:

#include <iostream>
using namespace std;

// 函数声明
double getAverage(int *arr, int size);

int main()
{
	// 带有 5 个元素的整型数组
	int balance[5] = { 1000, 2, 3, 17, 50 };
	double avg;

	// 传递一个指向数组的指针作为参数
	avg = getAverage(balance, 5);

	// 输出返回值
	cout << "Average value is: " << avg << endl;

	return 0;
}

double getAverage(int *arr, int size)
{
	int i, sum = 0;
	double avg;

	for (i = 0; i < size; ++i)
	{
         sum += arr[i];
	}

	avg = double(sum) / size;

	return avg;
}Code language: PHP (php)

可以通过指针来和下标来获取每个元素的值

int ages[3] = {1,20,45};
int *prt = ages;
for(int i = 0;i<3;i++)
{
   //cout << ages[i] << endl;
   cout << prt[i] << endl;//直接通过指针和下标来读取数组的每个元素 
}Code language: JavaScript (javascript)

函数返回指针

我们先来复习一下 以前函数的写法

#include <iostream>
using namespace std;

//以前的函数的写法 返回一个整数 
int getMax(int a,int b)
{
	if(a > b)
	{
		return a;
	}
	else 
	{
		return b;
	}
}
 
int main()
{
	int x = 23;
	int y = 54;
	int r = getMax(x,y);
	cout << r << endl; 
	
    return 0;
}Code language: PHP (php)

C++ 允许您从函数返回指针。为了做到这点,您必须声明一个返回指针的函数,如下所示:

int* myFunction()
{

}Code language: CSS (css)

如果把上面的改为返回指针

#include <iostream>
using namespace std;

//以前的函数的写法 返回一个整数 
int * getMax(int a,int b)
{
	if(a > b)
	{
		return &a;
	}
	else 
	{
		return &b;
	}
}
 
int main()
{
	int x = 23;
	int y = 54;
	int *r = getMax(x,y);
	y = 120;
	cout << *r << endl; 
	
    return 0;
}Code language: PHP (php)

现在,让我们来看下面的函数,它会生成 10 个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回它们,具体如下:

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

int * getRandom()
{
	static int  r[10];
	// 设置种子
	srand((unsigned)time(NULL));
	for (int i = 0; i < 10; ++i)
	{
		r[i] = rand();
		cout << r[i] << endl;
	}

	return r; //返回来的是数组的第一个元素的地址 
}
 
int main()
{
    //一个指向整数的指针
	int *p;

	//调用函数 函数返回指针
	p = getRandom();

	//通过指针 读取里面的值
	for (int i = 0; i < 10; i++)
	{
		cout << "*(p + " << i << ") : ";
		cout << *(p + i) << endl; //通过递增指针 读取里面的值
	} 
	
    return 0;
}Code language: PHP (php)

引用

引用和指针有点类似。但是并不是指针。

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

int a = 1;

假设给 a 起一个别名,可以理解为绰号。

就好比一个人有两个名字。那么这两个名字 一个叫变量名 一个叫引用 那么这两个名字 都可以表示这个人。

int a = 1;
int b = a; //把a的值 付给b 那么b的值也是1 a和b 在这里是没有关系。只是把b的值改为和a的值一样。Code language: JavaScript (javascript)

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。

引用的声明方法:类型标识符 &引用名=目标变量名;

【例1】:

int a; 
int &ra=a; //定义引用ra,它是变量a的引用,即别名Code language: JavaScript (javascript)

说明:

(1)& 在此不是求地址运算,而是起标识作用。

(2)类型标识符是指目标变量的类型。

(3)声明引用时,必须同时对其进行初始化。

(4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。

ra=1; 等价于 a=1;

(5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra 与 &a 相等。

(6)不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。

int a = 1; 
int &ra=a; //定义引用ra,它是变量a的引用,即别名	

cout << ra << endl;
ra = 2;
cout << a << endl;
return 0;Code language: JavaScript (javascript)

C++ 引用 vs 指针

引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

创建引用

试想变量名称是变量附属在内存位置中的标签,您可以把引用当成是变量附属在内存位置中的第二个标签。

因此,您可以通过原始变量名称或引用来访问变量的内容。例如:

int i = 17;

我们可以为 i 声明引用变量,如下所示:

int&  r = i;
double& s = d;

在这些声明中,& 读作引用。因此,第一个声明可以读作 “r 是一个初始化为 i 的整型引用”,第二个声明可以读作 “s 是一个初始化为 d 的 double 型引用”。下面的实例使用了 int 和 double 引用:

#include <iostream>
using namespace std;

int main()
{
	// 声明简单的变量
	int    i;
	double d;

	// 声明引用变量
	int&    r = i;
	double& s = d;

	i = 5;
	cout << "Value of i : " << i << endl;
	cout << "Value of i reference : " << r << endl;

	d = 11.7;
	cout << "Value of d : " << d << endl;
	cout << "Value of d reference : " << s << endl;

	return 0;
}Code language: PHP (php)
int a = 1; 
//int &ra; //不能创建空引用 

int *pa = &a;
int b = 2;
pa = &b;

int &ra = a; //引用创建的时候 必须绑定一个变量 
//&ra = b; //引用一旦创建 就不能更改  

float &rf = a;//类型要和变量一样 
return 0;Code language: JavaScript (javascript)

引用作为函数参数

下面的实例使用了引用来实现引用调用函数。

#include <iostream>
using namespace std;

// 函数声明
void swap(int& x, int& y);

int main()
{
	// 局部变量声明
	int a = 100;
	int b = 200;

	cout << "交换前,a 的值:" << a << endl;
	cout << "交换前,b 的值:" << b << endl;

	/* 调用函数来交换值 */
	swap(a, b);

	cout << "交换后,a 的值:" << a << endl;
	cout << "交换后,b 的值:" << b << endl;

	return 0;
}

// 函数定义
void swap(int& x, int& y)
{
	int temp;
	temp = x; /* 保存地址 x 的值 */
	x = y;    /* 把 y 赋值给 x */
	y = temp; /* 把 x 赋值给 y  */

	return;
}Code language: PHP (php)

如果不使用引用

#include <iostream>
using namespace std;

void Swap(int a,int b);

int main()
{
	int x = 23;
	int y = 12;
	Swap(x,y);
	cout << "x:"<<x << endl;
	cout << "y:"<<y << endl;
    return 0;
}

void Swap(int a,int b)
{
	int temp = a;
	a = b;
	b = temp;
}Code language: PHP (php)

a b 和 x y 完全是两个不同的变量 所以 a b 交换了 不影响 x y

如果把它换成引用参数 那么就可以解决这个问题了

#include <iostream>
using namespace std;

void Swap(int &a,int& b);

int main()
{
	int x = 23;
	int y = 12;
	Swap(x,y);
	cout << "x:"<<x << endl;
	cout << "y:"<<y << endl;
    return 0;
}

void Swap(int& a,int &b)
{
	int temp = a;
	a = b;
	b = temp;
}Code language: PHP (php)

如果使用引用,那么 x 和 a 是一个变量,a 是 x 的别名;y 和 b 是一个变量,b 是 y 的别名。

通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。C++ 函数可以返回一个引用,方式与返回一个指针类似。

当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:

#include <iostream>
using namespace std;

double vals[] = { 10.1, 12.6, 33.1, 24.1, 50.0 };

double &setValues(int i)
{
	return vals[i];   // 返回第 i 个元素的引用
}

// 要调用上面定义函数的主函数
int main()
{
	cout << "改变前的值" << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << "vals[" << i << "] = ";
		cout << vals[i] << endl;
	}

	setValues(1) = 20.23; // 改变第 2 个元素 之所以可以把一个值付给一个引用 是因为这个函数是返回一个引用 
	setValues(3) = 70.8;  // 改变第 4 个元素

	//相当于 返回一个变量 所以我们可以给这个变量赋值

	cout << "改变后的值" << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << "vals[" << i << "] = ";
		cout << vals[i] << endl;
	}
	return 0;
}Code language: PHP (php)

之所以可以把一个值付给一个引用,是因为这个函数是返回一个引用。

引用返回的函数 是在 = 号的左边,这个比较特别。

Previous:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注