C++参数传递:传值和传引用

C++参数传递:传值和传引用

C++不允许函数return数组或多个对象,但很多时候,确实需要一个函数传回多个值。这时就希望函数直接对外部的变量或指针做操作,绕过return来达到目的。引用的概念曾经一直是盲区,觉得&仅可能是取地址符,&a就是取a的地址的意思。由此导致很多错误。

引用

在《C++ Primer》(中文第五版,45~46页)中讲到,引用其实是给变量取了一个别名:

int a = 1;
int &ra = a; // ra是a的另一个名字

这时可以讲,raa指的完全是一个东西,任何对ra的操作都是对a的操作。在初始化的过程中,a的值并没有被复制。引用在定义的时候就必须被初始化,并且之后不能重新赋值。

就像*号在定义和声明过程中代表变量是一个指针,但在赋值等过程中代表解引用符来访问指针所指的对象一样,&符号在定义引用时,并不是取地址的意思。

函数传值

传值参数

当初始化一个非引用类型的变量时,初始值被拷贝给变量。此时,对变量的改动不会影响初始值。

也就是说,当一个函数被调用时,

void func(int p){p++;}

int main()
{
	int a = 1;
	func(a);
	return 0;
}

实际上是用a的值对形式参数p初始化,(相当于隐含了一句int p = a;),a这个对象被复制了一份。这时,pa是独立的两个变量,相互不影响。

要同时对多个变量做改变,并且在内部变量生命周期结束后,他们的变化还能影响到外部变量,这时可以声明指针变量做形式参数,

// 交换两个变量的值
#include <iostream>
using namespace std;

int main()
{
	int a = 1;
	int b = 2;
	int *p = &a;
	int *q = &b;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;	
	exchange(&a, &b); // 传入对象的地址而不是对象,以此初始化形式参数
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	return 0;
}

int exchange(int *p,int *q)
{
	int tmp = *p;
	*p = *q; // 对指针所指的对象做改变,但不改变指针所指向的地址
	*q = tmp; 
	return 0;
}

在函数内部利用解引用符,直接对存在于相应地址上的对象做改变。这样,当函数执行完毕,pq两个指针变量被销毁,ab的值被交换。

这也是指针的好处之一吧,可以实现很灵活的操作。

传引用参数

类似地,如果函数的形式参数是一个引用,在调用这个函数时,仍然使用初始值对形式参数进行初始化,相当于隐含了一个引用的初始化过程int &p = a;

int exchange2(int &a,int &b)  // 调用时要传入对象而不是对象的地址
{
	int tmp = a;
	a = b;
	b = tmp;
	return 0;
}

这样,并没有对象被复制,而是给外部变量a起了一个别名。可以理解为,在函数内部,p就是a,对p的改变就是对a的改变。

与值传递相比,引用传递的优势主要体现在三个方面:一是可以直接操作引用形参所引的对象;二是使用引用形参可以避免拷贝大的类类型对象或容器类型对象;三是使用引用形参可以帮助我们从参数中返回多个值

有的时候,函数只读取某个外部对象,并不希望对它做改变,这时,使用常量引用const int &p,这样可以防止对对象做改变。

发布了29 篇原创文章 · 获赞 3 · 访问量 6695

猜你喜欢

转载自blog.csdn.net/weixin_43316938/article/details/97935922