C#中引用与C++中指针和引用以及参数的传递

问题是什么
刚接触C#不久,对于值类型和引用类型的区别还是有点糊涂。后来看了一个不能工作的Swap()(下面有示例)方法之后,才发现,其实引用类型相当于C/C++中的指针——因为有声明:“string aStr = null;”是正确的。为了让自己以后可以追溯一下,所以把今天的理解记录下来,写在这里。

如何理解
C#中关于引用类型的定义是这样的:
“……值类型与引用类型的基本区别是他们在内存中的存储方式。……引用类型变量的地址存放在栈上,但实际的对象存放在堆上。……”
 
在上一篇文章里我说过,指针其实是一个ulong,从上面的描述中可以看出,引用类型其实也是一个ulong(地址),也就是说,“Object obj;”中,obj被分成两部分,一部分是其地址,另一部分是真正的Object实例。这两部分紧密联系在一起,形成一个引用类型对象。
 
引用类型的定义暗示我们,C#中引用类型相当于C++的指针,只不过C#语言本身作了一些工作,将指针和其指向的对象紧密地联系在一起了。只不过我们无法通过强制类型转换来获取这个值——也许有,但是我比较菜,不知道,呵呵。另外,引用类型的定义还暗示我们,C/C++函数调用时以传值方式传递参数的规则,在C#中同样有效。最简单的例子:
// C# code. Non dereferencing.
public void Swap<T>(T lhs, T rhs)
{
    T temp = lhs;
    lhs = rhs;
    rhs = temp;
}
调用该函数结果是什么样子呢?运行一下下面的代码就知道结果:传进去的引用类型的对象根本就没有改变(以string为例):
string a = "aaaa";
string b = "bbbb";
Swap<string>(a, b);
System.Console.WriteLine("a = " + a + ", b = " + b);
输出结果:a = aaaa, b = bbbb
 
因为实际上是对地址进行操作,传入的参数就是地址,因此可以将其翻译成C++(方便起见,使用int类型):
// C++ code. Non dereferencing.
template <class T>
void Swap(T * lhs, T * rhs)
{
    T * ptemp = lhs;
    lhs = rhs;
    rhs = ptemp;
}
这个函数也不能达到交换实参的目的,因为此处操作的是地址,与上一个例子一样。也就是说,C/C++和C#中函数调用时以传值方式传递参数。
 
那么为什么不是与C++的引用相似呢?可以看以下代码:
// C++ code
template <class T>
void Swap(T& lhs, T& rhs)

{
    int temp = lhs;
    lhs = rhs;
    lhs = temp;
}
对这个函数的调用将正确的交换两个实参。
 
C#要想通过函数调用来修改引用类型的对象,有两种方式:
1、dereference该引用以获取实际对象,即改变存放在堆上的对象本身,而不是存放在栈上的地址(没有进行dereference),这与C++的指针是相同的,也是前两个例子说明的问题。用deference的话,而且T实现了拷贝自身的方法,那么实现如下:
// C# code. Dereferencing.
// NOTE: T must have CopyTo() method.
public void Swap<T>(T lhs, T rhs)
{
    T temp = new T();
    lhs.CopyTo(temp);
    rhs.CopyTo(lhs);
    temp.CopyTo(rhs);
}
翻译成C++,就是如下代码:
// C++ code. Dereferencing.
// NOTE: T must have operator "=" overloaded.
template <class T>
void Swap(T * lhs, T * rhs)
{
    int temp = *lhs;
    *lhs = *rhs;
    *rhs = temp;
}

2、使用ref修饰符(从另一个角度说明C#引用的行为更像C++的指针),如下:
//可以工作的Swap
// NOTE: T doesn't need to have CopyTo() method implemented.
//       If you don't need to modify the reference itself, "ref" is not needed.
private void Swap<T>(ref T lhs, ref T rhs)
{
    T temp = lhs;
    lhs = rhs;
    rhs = temp;
}
原因很简单,使用了ref,将其翻译成C++就是:
/ C++ code. Dereferencing.
// NOTE: T doesn't need to have operator "=" overloaded.
template<T>
void Swap(T **lhs, T **rhs)
{
    T * temp = *lhs;
    *lhs = *rhs;
    *rhs = temp;
}

至于这里面涉及到的应该使用引用还是指针的问题,那就是另外一个话题了。关于指针本身,可以参考“ 指针是通往地狱的捷径”。

PS:由于对C#水平实在太浅,理解难免出现偏差,任何错误,请大虾指正!上述代码均为合法代码。

参考:
Programming C#, 3rd edition.
MSDN: Generic Methods (C# Programming Guide)
 
Copyleft (C) 2007-2009 raof01.
本文可以用于除商业外的所有用途。此处“用途”包括(但不限于)拷贝/翻译(部分或全部),不包括根据本文描述来产生代码及思想。若用于非商业,请保留此权利声明,并标明文章原始地址和作者信息;若要用于商业,请与作者联系(raof01@gmail.com),否则作者将使用法律来保证权利。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
CSharp 调用C++ DLL; 参数指针类型导出函数 c# Csharp调用 c++参数为导入和导出指针两种 包含C++ DLL源码 如fun(cont char* A,char*B) A为输入参数,B为输出参数-C# CSharp call C++ DLL lib dll function param use export and import eg: fun(cont char* A,char*B) A IN,B OUT TestDll\Debug\TestCallDll.exe .......\.....\TestCallDll.vshost.exe .......\.....\TestCallDll.vshost.exe.manifest .......\.....\TestDll.dll .......\.....\TestDll.lib .......\TestCallDll\Form1.cs .......\...........\Form1.Designer.cs .......\...........\Form1.resx .......\...........\obj\Debug\TestCallDll.csproj.FileListAbsolute.txt .......\...........\...\.....\TestCallDll.csproj.GenerateResource.Cache .......\...........\...\.....\TestCallDll.exe .......\...........\...\.....\TestCallDll.Form1.resources .......\...........\...\.....\TestCallDll.pdb .......\...........\...\.....\TestCallDll.Properties.Resources.resources .......\...........\Program.cs .......\...........\...perties\AssemblyInfo.cs .......\...........\..........\Resources.Designer.cs .......\...........\..........\Resources.resx .......\...........\..........\Settings.Designer.cs .......\...........\..........\Settings.settings .......\...........\TestCallDll.csproj .......\....Dll\dllmain.cpp .......\.......\ReadMe.txt .......\.......\stdafx.cpp .......\.......\stdafx.h .......\.......\targetver.h .......\.......\TestDll.cpp .......\.......\TestDll.def .......\.......\TestDll.h .......\.......\TestDll.vcproj .......\.......\TestDll.vcproj.PC-201008261742.Administrator.user .......\TestDll.sln .......\TestDll.suo .......\....CallDll\obj\Debug\TempPE .......\...........\...\Debug .......\...........\obj .......\...........\Properties .......\Debug .......\TestCallDll .......\TestDll TestDll

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值