最近在把一个大型的C++程序移植部分内容到C#上,其中有大量的C#与C++双向交互。再封装接口的时候出现了不少对基础概念的考察,也巩固了对基础概念和C++与C#不同点的理解。在此记录下来。
今天先记录下C++和C#有关值类型和引用类型的区别。
对于C++来说,如果在函数中不标明&引用,就是按值传递。貌似除了数组是默认指针外,其他都是按值传递。自己编写了有关类和struct的程序进行了验证。
#include "stdafx.h"
#include <iostream>
using namespace std;
struct BPTest
{
public:
int val;
struct BPTest(int dfvalue)
{
val=dfvalue;
}
};
void SetVal2(BPTest* t,int tval)
{
t->val=tval;
return;
}
void SetVal1(BPTest t,int tval)
{
t.val=tval;
return;
}
void SetVal3(BPTest&t,int tval)
{
t.val=tval;
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
BPTest t1(1);
BPTest* t2=new BPTest(2);
BPTest t3(3);
SetVal1(t1,10);
SetVal2(t2,10);
SetVal3(t3,10);
cout<<"t1: "<<t1.val<<"\n";
cout<<"t2: "<<t2->val<<"\n";
cout<<"t3: "<<t3.val<<"\n";
getchar();
return 0;
}
结果输出
t1: 1
t2:10
t3:10
把Struct换成Class的话,结果实测一样。
小结:可以看到,SetVal1实际是按值传递,做了类或struct的副本,所以更改不了原有类的值。SetVal2和3传递的相当于都是BPTest的对象地址,所以进行了修改。
进一步可以看到:c++里不像C#进行了值类型和引用类型的区分。
再谈一下C#的ref,值类型很好理解,如果对引用类型使用ref会产生什么效果呢?
看下面代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BPCSharp
{
class Program
{
public int val;
public static void ChangeProperty(Program p1)
{
p1.val=111;
return;
}
public static void ChangeSelf(Program p)
{
p=new Program(222);
Console.WriteLine("changeself {0}", p.val);
return;
}
public static void ChangeSelf2(ref Program p)
{
p=new Program(333);
return;
}
public Program(int inVal)
{
val=inVal;
}
static void Main(string[] args)
{
Program p1=new Program(10);
Program p2 = p1;
Program p3 = new Program(30);
Program p4 = p3;
Program.ChangeProperty(p1);
Console.WriteLine("p1 {0},p2 {1}", p1.val, p2.val);
Program.ChangeSelf(p1);
Console.WriteLine("p1 {0},p2 {1}", p1.val,p2.val);
Program.ChangeSelf2(ref p3);
Console.WriteLine("p3 {0},p4 {1}", p3.val, p4.val);
Console.ReadLine();
}
}
}
结果输出
p1:111 p2::111
changeself:222
p1:111 p2::111
p3:333 p4:30
小结:ChangeProperty是按引用传递更改自身参数,所以p1,p1都有修改;
Changeself传入p1的引用,实际产生这个引用的副本,其存储的地址与p1和p2一样,指向p1数据存储的地址,函数内部将此引用变换成了一个新的地址,指向new Program(222),所以原来p1 p2没有变,只有函数内部的引用副本变化了。
ChangeSelf2传入p3引用的引用,既p3引用的存放地址,因此修改此值会让p3引用中存储的地址变化,指向new Program(333)的数据地址,因此p3变化,p4没有变化。
因此,C#中对引用使用ref是有不同的,需谨记!