用交换函数讲解在函数调用时的值传递、指针传递、引用传递

变量的作用域

在C++程序中,我们所定义的函数名、变量名等名字,都由作用域来划分其可见范围。作用域指,在程序中用花括号括起来的代码块。在所有函数体之外定义的对象拥有全局作用域,为全局变量,在程序的任何地方都可访问。在花括号内定义的名字拥有块作用域,为局部变量,只在该块内部以及嵌套在块中的子块内可访问。通常,名字在作用域的有限区间内可见,从名字定义的位置开始,到名字所在的(最内层)作用域的结尾为止。

以下代码对程序的作用域做了说明:

#include<iostream>
#include<string>

using namespace std;

int a=5; // 变量a定义于所有花括号之外,拥有全局作用域,在整个程序范围内都可以访问

// swap拥有全局作用域
// 形参为在函数的形参列表中声明的局部变量,拥有块作用域,为局部变量,当前代码块内可用
void swap(int &v1, int &v2) 
{
	int temp = v2; // 定义在块内的局部变量,仅在块内可访问
	v2 = v1;
	v1 = temp;
}

int main() 
{
   a=10; // 在当前作用域内访问全局变量a
   swap(a,6); // swap在整个程序范围内可调用
}

怎样执行函数?

我们通过调用运算符来执行函数。调用运算符是一对圆括号,它作用于一个表达式,该表达式是函数或指向函数的指针;圆括号之内是实参列表,我们用实参初始化函数的形参,即,将实参的值拷贝给形参(参数类型为非引用,如果为引用则是将形参和和实参对象进行绑定)。调用表达式的类型是函数的返回值类型。

int ri(int w, int n)
{
   cout<<"调用执行函数"<<endl;
}

int main()
{
   int a=6;
   int b=9;
   ri(a,b); // 调用运算符作用于函数表达式
}

函数调用时发生了什么?

在main函数中,当程序运行到函数调用语句时:

          首先,用实参初始化形参

          其次,代码将进入被调用函数内执行

          然后,遇到return语句时函数结束执行

          最后,程序从被调函数转到主调函数继续执行,返回return语句中的值(若函数有返回值),函数的返回值用于初始化调用表达式的结果。并将被调函数运行时为局部对象申请的内存资源销毁(局部静态对象除外)。

参数传递

函数调用时,实参对形参进行初始化的机理与变量的初始化一样。如果形参是引用类型,它将绑定到对应的实参上;否则,将实参的值拷贝后赋值给形参。

  1. 非引用传递

值传递:

将实参的值拷贝给形参后,实参和形参是相互独立的对象。形参的改变不会使实参改变。实参和形参本质上讲只是一个为变量赋值的操作,初始值被拷贝给对象,此时,对变量的改动不会影响初始值,也就是实参。所以,此交换函数并不能实现变量的交换。

//交换两个变量的值
void ti(int u1,int u2)
{
    int d=u1;
    u1=u2;
    u2=d;
}

int main()
{
   int a=6;
   int b=9;
   ti(a,b);
   cout<<"a="<<a<<endl<<"b="<<b<<endl;
}

输出结果:

指针传递:

函数的形参类型为指针类型时,其本质还是值传递,拷贝的是指针变量。拷贝之后,两个指针变量是不同的指针变量,但它们所指的是同一个内存空间。

case1: 虽然形参是指针类型,实参对形参的初始化也传递的是mm和nn的地址值,交换函数内部虽然交换的是mm和nn的地址值,但并未交换mm和nn所指向的对象的值。

void swap1(int *r1, int *r2)
{
	int *u = r1;
	r1 = r2;
	r2 = u;
}

int main()
{
    int mm = 6;
	int nn = 10;
	swap1(&mm, &nn);
	cout << "mm=" << mm << endl << "nn=" << nn << endl;
}

输出结果:

case2: 那么,我们可以直接用被初始化后的形参,通过解引用访问mmm和nnn的值,并直接对其值进行交换:

void swap2(int *r1, int *r2)
{
	int u = *r1;
	*r1 = *r2;
	*r2 = u;
}

int main()
{
    int mmm = 6;
    int nnn = 10;
	swap2(&mmm, &nnn);
	cout << "mmm=" << mmm << endl << "nnn=" << nnn << endl;
}

 输出结果:

     2. 引用传递

 当形参是引用类型时,实参对形参的初始化实则是实参绑定了形参,形参是实参的别名,对形参的改变也就是对实参的改变。

void swap3(int &r1, int &r2)
{
	int u = r1;
	r1 = r2;
	r2 = u;
}

int main()
{
    int mmmm = 6;
    int nnnn = 10;
	swap2(&mmmm, &nnnn);
	cout << "mmmm=" << mmmm << endl << "nnnn=" << nnnn << endl;
}

输出结果:

 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值