学习C# 引用传递与ref关键字:与 C++ 的对比分析

在 C# 中,方法参数的传递方式是一个重要的概念,尤其是在处理引用类型时。尽管引用类型的对象是通过引用传递的,但传递的实际上是引用的副本。这意味着修改引用的指向不会影响原始对象的引用指向。

直接看代码,我写了一个基本的学生类和一个交换学生信息的函数:

 class Student
 {
     int id;
     string name;
     Student(int id,string name) 
     {
         this.id = id;
         this.name = name;
     }


     static void Main(string[] args)
     {
         Student a = new Student(1, "小a");
         Student b = new Student(2, "小b");
         SwapStudent(a, b);
         Console.WriteLine($"{a.id} {a.name}");
         Console.WriteLine($"{b.id} {b.name}");
     }

     public static void SwapStudent(Student s1 , Student s2)
     {
         Student temp = s1;
         s1 = s2;
         s2 = temp;
     }

 }

如果你认为打印之后,输出的是2 小b    1 小a

那你就和我犯了相同的错误!实际上输出的还是1 小a    2 小b

我原本认为,这不是引用类型吗,传递的是引用啊,我修改了引用的指向,那么原对象的信息应该会交换啊?后来经过学习才发现:

在 C# 中,引用类型存储的是对象的内存地址,指向该对象在堆中的实际数据。当你传递一个引用类型的对象时,传递的是这个对象的引用的副本,而不是原始的引用

这意味着:

  • 如果你修改引用所指向对象的属性,由于两个引用指向同一个对象,所以这些修改会影响到原对象。
  • 如果你重新赋值引用本身,这个赋值只会影响这个副本引用,而不会影响原始引用。

同理,在C++中传递指针时,也是类似的,传递的是指针的副本而非原始的指针。

那么可能你就想问了,那我就没有办法传递原始的引用吗?我就想在函数中修改引用的指向!

答案是有的—— ref !我们来修改一下代码

        static void Main(string[] args)
        {
            Student a = new Student(1, "小a");
            Student b = new Student(2, "小b");
            SwapStudent(ref a, ref b);
            Console.WriteLine($"{a.id} {a.name}");
            Console.WriteLine($"{b.id} {b.name}");
        }

        public static void SwapStudent(ref Student s1 , ref Student s2)
        {
            Student temp = s1;
            s1 = s2;
            s2 = temp;
        }

加了ref关键字后,函数接收到的是变量的实际引用。通过这种方式,函数内部修改引用的指向会影响外部的实际变量,因此就可以正确地交换两个变量了。

明白以后,我开始思考,C++中没有ref关键字,C++中可以通过&来传递引用,但是通过&传递的引用是不可以重新修改指向的,那C++中有没有办法实现类似C#中的ref的效果了吗?

gpt给了我这样的解答:

#include <iostream>
#include <string>

class Student {
public:
    int id;
    std::string name;

    Student(int id, const std::string& name) {
        this->id = id;
        this->name = name;
    }
};

// 交换学生对象的函数,使用指针的指针
void SwapStudent(Student** s1, Student** s2) {
    Student* temp = *s1; // 保存原 s1 的指向
    *s1 = *s2;           // 将 s1 指向 s2
    *s2 = temp;         // 将 s2 指向原 s1
}

int main() {
    Student* a = new Student(1, "小a");
    Student* b = new Student(2, "小b");

    SwapStudent(&a, &b); // 传递指针的地址

    std::cout << a->id << " " << a->name << std::endl; // 输出 2 小b
    std::cout << b->id << " " << b->name << std::endl; // 输出 1 小a

    // 清理内存
    delete a;
    delete b;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值