C#中值类型和引用类型的区别
发布网友
发布时间:2022-04-24 18:09
我来回答
共10个回答
懂视网
时间:2022-05-16 11:19
<script type="text/javascript">
var i = 1;
var j = 2;
var a = [1, 2];
function arr(b) {
b[0] = 2;
}
function me(x, y) {
x = x+y;
return x;
}
arr(a);
console.log(i); // 1
console.log(JSON.stringify(a)); // [2,2]
</script>
热心网友
时间:2022-05-16 08:27
1、速度上的区别
值类型存取速度快,引用类型存取速度慢。
2、用途上的区别
值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用。
3、来源上的区别
值类型继承自System.ValueType,引用类型继承自System.Object
4、位置上的区别
值类型的数据存储在内存的栈中,引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。
5、类型上的区别
值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。
6、保存位置上的区别
值类型变量直接把变量的值保存在堆栈中,引用类型的变量把实际数据的地址保存在堆栈中,而实际数据则保存在堆中。
例如:
字符串类型,而堆栈则用于存储固定长度的数据,如整型类型的数据int(每个int变量占用四个字节)。
由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。
在进行数据操作时,对于值类型,由于每个变量都有自己的值,因此对一个变量的操作不会影响到其它变量;对于引用类型的变量,对一个变量的数据进行操作就是对这个变量在堆中的数据进行操作,
如果两个引用类型的变量引用同一个对象,实际含义就是它们在堆栈中保存的堆的地址相同,因此对一个变量的操作就会影响到引用同一个对象的另一个变量。
热心网友
时间:2022-05-16 09:45
值类型、引用类型区别:
值类型内容存储在(栈)上。引用类型指针存储在(栈)上,内容存储在(堆)上。
值类型和引用类型最大的不同是:传递的效率和影响:效率指:软件运行时,复杂功能在大量运算,毫秒级上内存一直在复制和分配,一组数据的值拷贝和指针拷贝,cpu性能和内存表现差异大,影响指:修改方法里的数据会不会影响到方法外的数据对象。
值类型=其他变量时是复制内容(替换栈内容),引用类型=其他变量时是替换指针(替换栈指针)。
值类型赋值时(例=1)是替换内容(替换栈内容),引用类型=new时是新分配内存(新分配堆内存)和替换指针(替换栈指针)。
值类型在方法传递参数过程中是复制1份内容(新分配栈内容),引用类型在方法传递过程中是复制1个指针(新分配栈指针),指向同1个内容,内容没复制。
值类型在方法里修改不影响方法外变量,引用类型在方法里修改,因为指向同1个内容,方法外的值也同步变化。
字符串是特殊的引用类型:
字符串是特殊的引用类型,每次=新字符串实际都改变一次栈指针(新分配堆内存,替换栈指针),而没有改变值。
字符串传给方法是1个指针(新分配栈指针)。方法内=新字符串是替换方法内的指针(替换新栈指针),不影响方法外的指针(不影响原栈指针),所以表现看过去与值传递一致。
结构体struct值类型、class引用类型区别:
结构体struct是值类型,但是结构体中的字符串、数组、类存放的是指针,和值一起存在栈上。
所谓值类型, 结构体的表现就是传给方法是复制1套指针和1套值,在方法内修改结构体1级属性(修改结构体字符串、new数组、new类)改的是方法内结构体的指针(1级指针),无法改变方法外结构体的指针,所以不影响方法外的结构体,但是修改数组内数据和类属性会影响方法外的结构体(因为改的是1级指针指向的内容)。
class是引用类型,传给方法是1个指针。方法内替换属性会影响方法外的对象(因为修改的是指针指向的内容)。但是方法内再次=new对象是替换方法内的对象指针,不影响方法外的对象,再替换属性就不影响方法外的对象。
热心网友
时间:2022-05-16 11:19
每一个值类型都有一个独立的内存区域保存自己的值,调用它的时候调用的是他的值,而应用类型调用的是内存中的地址。
比如a1=18,这时候在内存中保存的是18,当把a1赋值给a2的时候,他们两个引用的是同一个内存空间,a2的值会保存为a1的值,当把a2改为20后,因为a1和a2引用的是同一个内存地址,所以a1也变成20,这是引用类型。
值类型是当把a1赋值给a2时,会为a2再开一块新的内存空间保存a1的值。当把a2改成20时,只会在a2的空间保存20,和a1没关系了。
热心网友
时间:2022-05-16 13:11
值类型都是深拷贝,就是把内存中的数据赋值给另一快内存。
引用类型都是浅拷贝,就是被指向一块内存的地址拷贝给了另一个引用。
值类型用=是值传递
会在内存中在开辟一块新的内存,
比如
int
a
=
1;
int
b
=
a;
内存中就开了2快内存分别是a和b,结构也是值类型
所以没问题。问题在于类,如果你没有写“=”号赋值运算符,那么student3
=
student4;让student3也指向student4的内存,然后你再给student4这块内存赋值20
那么student3就也等于20了。而且ClassStudent
student3
=
new
ClassStudent();这块内存,如果没有.net的垃圾回收的话,在C++中就是内存泄露了。
热心网友
时间:2022-05-16 15:19
1
值类型。
定义时只有类型和变量名。没有&符号的为值类型。表示本身的值。有自己的内存空间。可以不做初始化。
2
引用类型。
定义时,类型
&变量名=另一个变量名。
表示引用。自身没有内存空间,使用初始化时的变量空间。是另一个变量名的一个别名。
引用在定义时必须初始化。
热心网友
时间:2022-05-16 17:43
它们的区别在于使用的内存位置不同:值类型数据存储在栈上,而引用类型数据存储在堆上。
值类型直接包含值,换言之,变量引用的位置就是值在内存中实际存储的位置。
引用类型并不直接存储值,它们存储的是对一个内存位置的引用(内存地址),要去那个位置才能找到真正的数据。
------------------《C#本质论》(Essential C# 2.0)
热心网友
时间:2022-05-16 20:25
不知道你学过C没有,演过C的话就很好理解这个问题,引用相当于你在C里面使用指针,
如:写一个函数的时候
public int fuction1(ref int a,ret int b)
{
a=2 ,b=3
......}
public static main()
{
int a=1,b=2
function1(ref int a ,ref int b)
}
当你在function1中间把a,b变量的值改变后,main函数里面的a,b 值也就改变了
成了a=2,b=3了
热心网友
时间:2022-05-16 23:23
你得到的结果还是一样的确良20
和20
student3.age
=
18;
--->age=18;
student4
=
student3;
--->student4=18;
student4.age
=
20;
--->student4=20;
--->age=20先前那个age被替了
----->20,20
热心网友
时间:2022-05-17 02:37
举例:
应用类型:
数组(派生于System.Array)
用户用定义的以下类型:
类:class(派生于System.Object);
接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。Anders在《C# Programming Language》中说,接口只是表示一种约定[contract]);
委托:delegate(派生于System.Delegate)。
object(System.Object的别名);
字符串:string(System.String的别名)。
可以看出:
引用类型与值类型相同的是,结构体也可以实现接口;
引用类型可以派生出新的类型,而值类型不能;
引用类型可以包含null值,值类型不能(可空类型功能允许将 null 赋给值类型);
引用类型变量的赋值只复制对对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。
对于最后一条,经常混淆的是string。我曾经在一本书的一个早期版本上看到String变量比string变量效率高;我还经常听说String是引用类型,string是值类型,等等。
值类型 :
C#的所有值类型均隐式派生自System.ValueType:
结构体:struct(直接派生于System.ValueType);
数值类型:
整型:sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long (System.Int64),byte(System.Byte),ushort(System.UInt16),uint (System.UInt32),ulong(System.UInt64),char(System.Char);
浮点型:float(System.Single),double(System.Double);
用于财务计算的高精度decimal型:decimal(System.Decimal)。
bool型:bool(System.Boolean的别名);
用户定义的结构体(派生于System.ValueType)。
枚举:enum(派生于System.Enum);
可空类型(派生于System.Nullable<T>泛型结构体,T?实际上是System.Nullable<T>的别名)。
每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。
C# 支持两种变量类型:
• 值类型 — 这些是内置的基本数据类型,例如 char、int、float等基本数据类型(string除外) 、枚举以及用 struct 声明的用户定义类型。
• 引用类型 — 从基本类型构造而来的类和其他复杂数据类型。如:类、接口、数组和字符串。这种类型的变量并不包含类型的实例,而只是包含对实例的引用。
值类型和引用类型的区别在于他们在内存中的存储方式,值类型存贮在栈中,引用类型的内存单元中只存放对象的地址,而对象本身存贮在内存堆中。
值类型在内存中引用的时候会在堆栈中创建一个全新的副本,而不是简单的引用;而引用类型只是简单的引用对象的地址。