【C#】结构体struct的拷贝原理(浅拷贝)

文章探讨了C#中结构体struct的浅拷贝和深拷贝概念。浅拷贝创建新对象但引用类型仍共享内存,而深拷贝则为引用类型开辟新内存。在示例中,结构体成员的值类型(id)不受函数内修改影响,而引用类型(name和children数组)的修改会影响原对象。
摘要由CSDN通过智能技术生成


一、浅拷贝和深拷贝

  1. 浅拷贝:创建一个新对象,对于值类型,栈内容是其值本身;对于引用类型,其值是指向堆的内存地址(它们是共享内存的,如果原对象或新对象中的一个改变了这个地址上的值,就会影响到另一个对象)。
  2. 深拷贝:创建一个一摸一样的新对象,对于引用类型,它们是不共享内存的,新对象会从堆内存开辟一个新的区域存放(两者互不影响)。

二、结构体Struct

C#中 结构体struct 是值传递、浅拷贝
测试代码如下:

public struct Record
{
	public int id;
    public string name;
    public int[] children;
}

public static void DoSomething(Record record)
{
    record.id = 6;
    record.name = "Bob";
    record.children[0] = 7;
    unsafe
    {
        fixed (char* p2 = record.name)
        {
              Console.WriteLine((int)p2);
        }
    }
}

static void Main(string[] args)
{
    Record record = new Record();
    record.name = "Alice";
    record.children = new int[] { 1, 2, 3 };
    unsafe
    {
    	fixed (char* p1 = record.name)
    	{
         	Console.WriteLine((int)p1);
	    }
    }
    DoSomething(record);
    Console.WriteLine(string.Format("{0}-{1}-{2}",record.id
    	, record.name, record.children[0]));
}

上面的例子中,声明的结构体:
在调用DoSomething() 之前的值为: { 0,“Alice”,{1,2,3}}
在DoSomething()中,浅拷贝过来的值为 { 6,“Bob”,{7,2,3}}

  1. id 是 值类型,所以出了函数作用域就没有影响,

  2. name 是 string类型,在C#中属于引用类型。
    【C#在对一个字符串赋值时,是先为右值开辟新的内存空间,然后把右值的引用赋给左值】
    当它在函数域中被赋值为“Bob”时,其实是赋了一个新的地址(指向“Bob”的地址)给浅拷贝过来的地址,对原来的struct不起作用。
    (示例中的unsafe代码就是为了看出两个字符串的地址区别)

  3. children数组是引用类型,浅拷贝了它的引用给函数,函数中对引用的地址上的值进行了修改,会影响原来的struct。

所以执行完DoSomething()后 结构体值为 { 0,“Alice", { 7, 2, 3 }}
在这里插入图片描述


总结

结构体是值传递、浅拷贝
结构体成员中,对于引用类型,只拷贝引用,引用里的值不拷贝。
所以,浅拷贝后
对引用的指针位置修改,对struct不起作用。
对引用的地址上的值进行修改,会对struct起作用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
结构体拷贝可以分为深拷贝浅拷贝两种方式。 浅拷贝是指将一个结构体的值复制到另一个结构体中,包括结构体成员的基本数据类型和指针地址的复制。当进行浅拷贝时,只是复制了指针的地址,而没有复制指针指向的具体数据。这意味着如果其中一个结构体修改了指针指向的数据,另一个结构体也会受到影响。 深拷贝是指将一个结构体的值复制到另一个结构体中,并且对于指针类型的成员变量,还会将指针指向的数据进行复制。这样,在进行深拷贝后,每个结构体都有自己独立的数据副本,互不影响。 下面是一个示例,演示了浅拷贝和深拷贝的区别: ```c #include <stdio.h> #include <string.h> typedef struct { char* name; int age; } Person; void shallowCopy(Person* dest, Person* src) { dest->name = src->name; dest->age = src->age; } void deepCopy(Person* dest, Person* src) { dest->name = malloc(strlen(src->name) + 1); strcpy(dest->name, src->name); dest->age = src->age; } int main() { Person person1; person1.name = "John"; person1.age = 25; Person person2; // 浅拷贝 shallowCopy(&person2, &person1); printf("Shallow copy:\n"); printf("person1 name: %s, age: %d\n", person1.name, person1.age); printf("person2 name: %s, age: %d\n", person2.name, person2.age); // 修改person1的name person1.name = "David"; printf("After modifying person1 name:\n"); printf("person1 name: %s, age: %d\n", person1.name, person1.age); printf("person2 name: %s, age: %d\n", person2.name, person2.age); // person2的name也被修改了 // 深拷贝 deepCopy(&person2, &person1); printf("Deep copy:\n"); printf("person1 name: %s, age: %d\n", person1.name, person1.age); printf("person2 name: %s, age: %d\n", person2.name, person2.age); // 修改person1的name person1.name = "Mike"; printf("After modifying person1 name:\n"); printf("person1 name: %s, age: %d\n", person1.name, person1.age); printf("person2 name: %s, age: %d\n", person2.name,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葫芦娃子救我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值