C#的數據類型分爲兩類:值類型(基本的數據類型)和引用類型
值類型:byte,int,float,bool,struct.....
引用類型:string,數組,自定義的類,內置的類.....數組
咱們把內存分爲堆空間和棧空間
棧空間比較小,可是讀取速度快
堆空間比較大,可是讀取速度慢ide
棧只能從棧頂插入或刪除元素,相似於桶裝的薯片,先進後出
堆可以以任意順序插入或刪 除元素,堆裏面的每個元素都是程序中的一個引用
spa
CLR中的GC(Garbage Collector 垃圾回收器)就是內存管理機制,C#中不須要咱們關心內存的使用,由於CLR幫咱們作了
例如在堆中一共有兩個對象被程序引用着,當其中一個對象的引用斷開,GC發現沒有對象引用着它,那麼會自動釋放它的內存,釋放後這塊內存能夠被重用3d
值類型只須要一段單獨的內存去存儲實際的數據,通常在棧中存儲
引用類型須要兩段內存,一段存儲實際的數據,在堆中存儲,另外一段是一個引用,在棧中存儲,指向數據在堆中的存放位置(內存地址)orm
能夠拿在一個盒子裏裝吃的來分析:
值類型就是在盒子裏直接放了吃的
引用類型是在盒子裏放了一張紙條上面寫着吃的在哪個盒子裏對象
Q:Unity中爲何不能對transform.position.x直接賦值?blog
——第一種
當Test方法執行後會先清空棧中的內存,首先清空name的內存地址,而後清空bool類型變量c的內存,清空char類型變量b的內存,清空int類型變量a的內存,最後GC的引用計數器發現string類型liu的引用數爲0,則釋放堆中string類型liu的內存內存
——第二種(正常的引用類型)
當使用引用類型賦值時,其實賦值的是引用類型的引用(地址),並非實際值
當str[0]賦值b1時,操做的實際上是同一塊內存空間,並非操做的新的內存空間string
——第三種(特殊的引用類型,string類型比較特殊)
當使用引用類型賦值時,其實賦值的是引用類型的引用(地址),並非實際值
當str賦值chen時,是系統在堆中又開闢了一段新的內存空間去存儲string類型chen的實際值it
首先在堆中開闢一個內存空間(例如0X88)保存str1的值a1和a2,而後在棧中開闢一個內存空間保存地址0X88,當將str1賦值給str2時,是把str1的地址賦值給了str2的地址,即在棧中開闢了一個內存空間保存地址0X88,因此str1和str2引用着同一塊堆中的內存空間,當把b1賦值給str2[0]時,操做的是地址0X88對應在堆上保存的值,因此str1和str2是同樣的
首先在堆中開闢一個內存空間(例如0X88)保存str1的值liu,而後在棧中開闢一個內存空間保存地址0X88,當將str1賦值給str2時,是在堆中又開闢一個內存空間(例如0X11)保存str1的值liu,而後在棧中開闢一個內存空間保存地址0X11,接下來把chen賦值給str2時,是在堆中新開闢一個內存空間(例如0X22)來保存chen這個值,而後再把棧中str2保存的地址改成0X22,以後堆中0X11的內存空間會被垃圾回收掉
——第四種(比較容易混淆的)
v1,v2都是自定義類型,爲引用類型,當執行v1=v2時,v1與v2的內存地址都引用了同一塊堆中的實際內存區域,因此操做v1.x就至關於操做v2.x
——第五種
若是數組中的值是值類型,那麼數組中直接存儲值
若是數組中的值是引用類型,那麼數組中存儲的是引用(內存地址)
當執行Vector3 v1=v[0]時,v1的內存地址引用了堆中內存地址1,因此執行v[0].x與v1.x都是操做同一塊內存空間
char類型是值類型,存在在棧上,在編譯時要求分配內存,因此必須爲其賦初值,其餘值類型如int,double,枚舉,結構等都是如此 string是引用類型,在棧上存儲地址,堆上存儲值,在程序運行時動態的分配內存,因此容許在變量聲明時聲明爲null,不爲其分配內存