C++和C#中的引用传递和值传递

C++中按值传递对象时,会调用拷贝构造函数生成对象的副本,那么对应的C#中也是这样的吗?

无论是在C++中还是在C#中,当变量或对象作为函数参数进行传递时都有两种方式:按值传递和按引用传递。

所谓按值传递是指在函数体内部使用的是对象的副本,在C++中这个副本是调用对象的拷贝构造函数完成的,而函数对副本的修改不会影响原来的对象。如

//C++

void Fun1(Student ss)

{

    ... ...  //ss进行处理和修改――实际处理的是传入对象的副本

}

 ... ...

 Student s7 ;

 Fun1(s7) ;//此函数调用结束后,对象s7的状态并没有改变

... ...

所谓按引用传递是指传给函数的实际上是对象的地址,这样函数对对象的修改就会反应在对象中,使对象的状态发生变化。如

//C++

void Fun2(Student& ss)

{

    ... ...  //ss进行处理和修改

}

... ...

Student s8 ;

Fun2(s8) ;//此函数调用结束后,对象s8的状态发生改变

... ...

C++中,可以通过指针和“&”引用符实现引用传递。上面的例子用到了“&”引用符号,其实换成指针也可以达到同样的效果。如果我们再进一步去想,可以发现,当用指针进行引用传递时,也发生了复制,只不过复制的是指针的值(即对象的地址),而不是复制指针指向的对象。这可以通过如下例子得到证明。

//C++

void Fun3(Student* ss)

{

    ... ...  //ss指向的对象进行处理和修改

    ss = NULL ;

}

... ...

Student* s9 ;

Fun3(s9) ;//此函数调用结束后, s9指向的对象的状态发生了改变

... ...   

但是在Fun3s9)调用完后,s9并不是NULL ,这说明Fun3中使用的是指针s9的副本。如果再进一步,我们可以猜测用“&”符实现引用传递时也发生了同样的故事。事实上也是这样,C++中的引用只是一个受限却更加安全的指针而已。

那么按引用传递和按值传递各有什么好处了?

按引用传递不需要发生拷贝行为,因此速度快,特别是大对象时,这种优势很明显。按值传递时对传入对象的修改实际是对对象副本的修改,不会影响原对象的状态。

你也许会想到如果采用const引用传递那么就可以得到双倍的好处,可以这么说,但是不要走极端。

一般而言,将不允许改变的大对象作为const引用传递给函数是很合适的,但如果是简单类型或自定义的小对象直接用值传递就可以了。

 

如果外界一定要看到函数对对象的修改,那么只有一条路 ―― 按引用传递。

C#中情况却发生了变化,C#中的引用类型的对象都是按引用传递且只能按引用传递。而值类型对象(或者称为变量),通常情况下是按值传递的。如果要按引用传递值类型对象,那么就要使用关键字refout refout的唯一区别是ref用修饰参数时要求传入的变量被初始化过。

由于类是引用类型,而所有的引用类型的对象的传递都是引用传递,所以在此过程中根本不会发生拷贝函数的调用。照这样看来,根本就没有必要有拷贝构造函数了。

我想现在你已经知道了C# 中为什么不需要拷贝构造函数和很少调用赋值运算符了。你也许会问既然是很少调用赋值运算符,那一定还有调用赋值运算符的情况存在,那么这种情况是怎样的?那是因为类的相仿体――结构struct

原文地址:https://www.cnblogs.com/zcy_soft/p/1845816.html