看下面的程序:
#include <iostream>
using namespace std;
void Swap( int a , int b)
{
int c;
if(a>b)
{
c=a;
a=b;
b=c;
}
cout<<"The Value of X after Process is " << a <<endl;
cout<<"The Value of Y after Process is " << b <<endl;
}
int main()
{
int x,y;
x = 6;
y = 4;
Swap(x,y);
cout<<"The Value of X is "<< x <<endl;
cout<<"The Value of Y is "<< y <<endl;
}
这一段是C++程序,运行的时候会发现在调用Swap方法的之后,输出的结果X仍为6,Y仍为4,但是在Swap函数中,X和Y的值确实发生了变化,这是为什么呢?
这是因为在c++中,传入函数本身的并不是参数本身,而是参数的值,这样,即便参数的值发生了变化,也是处理的参数的值变化了,这些值存放在与X Y本身不同的内存空间,本例中即为a、b,他们的值的变化不会引起X Y值的变化。这一点可以在调试的时候发现,当Swap函数调用结束后,a,b中内存地址不再有效,已经在其中找不到任何内容了。
在C#中仿照C++的源代码我写了如下代码,发现C#和C++一样,也是使用的是值调用(单对int值):
using System;
using System.Collections.Generic;
using System.Text;
namespace REF
{
class Program
{
static void Main(string[] args)
{
int x = 6;
int y = 4;
Swap(x, y);
Console.WriteLine("The value of X is {0},The Value of Y is {1}", x, y);
}
static void Swap(int a, int b)
{
int c = 0;
if (a > b)
{
c = a;
a = b;
b = c;
}
}
}
}
输出结果为:
The Value of X is 6,The Value of Y is 4
那么要怎么解决这个问题呢?
先看一下C++环境下的解决方法:
#include <iostream>
using namespace std;
int Swap( int a , int b)
{
int c;
if(a>b)
{
c=a;
a=b;
b=c;
}
cout<<"The Value of X after Process is " << a <<endl;
cout<<"The Value of Y after Process is " << b <<endl;
return a;
}
int main()
{
int x,y,z;
x = 6;
y = 4;
z = Swap(x,y);
if(x != z)
{
y = x;
x = z;
}
cout<<"The Value of X is "<< x <<endl;
cout<<"The Value of Y is "<< y <<endl;
}
可以看到,利用一个返回值来帮助处理主函数中的数据,使得两者之间产生联系。
输出结果为:
The Value of X is 4
The Value of Y is 6
The Value of X after Process is 4
The Value of Y after Process is 6
这样就实现了对XY的值经过处理之后值发生了变化。
但是这样的方法是一个间接的方法,有没有办法能够直接引用本内存地址的方法呢?
但是C#提供了一个更好的方法来实现功能。来看一下的代码:
using System;
using System.Collections.Generic;
using System.Text;
namespace REF
{
class Program
{
static void Main(string[] args)
{
int x = 6;
int y = 4;
Swap(x, y);
Console.WriteLine("The value of X is {0},The Value of Y is {1}", x, y);
Swap(ref x,ref y);
Console.WriteLine("The value of X is {0},The Value of Y is {1}", x, y);
Console.ReadLine();
}
static void Swap(ref int a,ref int b)
{
int c = 0;
if (a > b)
{
c = a;
a = b;
b = c;
}
}
static void Swap(int a, int b)
{
int c = 0;
if (a > b)
{
c = a;
a = b;
b = c;
}
}
}
}
这里我重载了Swap函数,并用关键字 ref 来处理。得到我想要的结果:
The Value of X is 6,The Value of Y is 4
The Value of Y is 4,The Value of X is 6
看到了,经过关键字ref 引用过的参数是按照参数进行传递的,不是使用值传递,这样便可以使得程序编制的时候充满了多样化,方便了用户的使用。
关键字ref 原理是这样的:当控制权交给回调函数(比如说是swap),由于引用了变量本身,使用的是变量本身的内存地址,而不是开辟一个新的内存地址,所作的所有改变自然也就会发生改变。
需要注意的是使用关键字ref 的时候,提前一定要声明引用的变量,原因很简单,要是没有声明变量,编译器就不知道到什么地方去提取这个变量的内存地址。