C 型別基礎 引用型別

2021-07-09 05:00:18 字數 3769 閱讀 4844

上一講說了一下值型別的部分內容,

雖然沒有什麼有意思的東西能吸引大家的注意

,也沒啥好的**讓大家參考一下

,但是樓主的水平實在有限

,各位看官如果不嫌棄的話

,還是看看吧

,如果對你的生活或者學習有那麼一絲幫助的話

,都算是樓主的萬幸

.當宣告乙個引用型別變數,

並使用new

操作符建立引用型別實力的時候

,該引用型別的變數會被分配到執行緒棧上

,變數儲存了位於堆上的引用型別的例項的記憶體位址

.變數本身不包含任何型別所定義的資料

.如果僅僅宣告乙個變數

,但不使用

new操作符

,由於在堆上還沒有建立型別的例項,因此

,變數值為

null,

意思是不指向任何物件

(堆上的物件的例項

).對於變數的型別宣告

,用於限制此變數可以儲存的型別例項的位址.

說明:這裡有一些概念可能容易混淆

,那就是變數

(variable),

物件(object),

例項(instance).

變數可以是乙個值型別

,也可以是乙個引用型別

.當變數是引用型別時

,由於本身只包含實際物件的引用

(記憶體位址

),因此也叫做物件引用

.而在物件建立的物件

,稱為物件的例項

(根據類的定義分配了記憶體

).從一段簡單的**也可以看出

,如果執行

object a=null;console.writeline(a.tostring());,

會得到執行時錯誤」未將物件引用設定到物件的例項」.因此變數

a是乙個物件引用

,因為沒有使用

new操作符

,所以它沒有指向任何的物件例項

.如果有乙個這樣的類,

它依然代表直線上的一點:

public class refpoint

public refpoint()

}

當僅僅寫下一條宣告語句時:

它的效果如下圖所示,

,也不知想任何物件的

(不包含記憶體位址

)的變數:

當使用new

操作符時

:rpoint1= new refpoint(1);

則會完成下面幾件事情:

1.在應用程式堆上建立乙個引用型別物件的例項,

並為它分配記憶體空間

.2.自動傳遞該例項的運用給建構函式.(

正因為如此

,才可以在建構函式中使用

this

來訪問這個例項

.)3.呼叫該型別的建構函式.

4.返回該例項的引用(

記憶體位址

),賦值給

rpoint1

變數,如下圖所示:

很多時候大家喜歡用int

型別作為值型別的例項,用

object

型別作為引用型別的例項來說明問題

.但是今天咱們採用自定義的結構和類

,分別對值型別和引用型別進行說明

.這是因為簡單型別(比如

int)

有一些框架類庫已經實現了的行為

,這些行為會讓我們對一些操作產生誤解

.或者說

,用他們作為示例還不夠純粹.

舉個例子,

如果我們想比較兩個

int型別是否相等

,通常會這樣:

int i=3;

int j=3;

if(i==j)

console.writeline(「 i equals to j 」);

但是,對於自定義的值型別

,比如結構

,就不能用」==」來判斷它們是否相等,

而需要在變數上呼叫

equals()

方法來完成.

再來個例子,

大家知道

string

是乙個引用型別

,在比較他們是否相等的時候

,通常會這樣做:

string a=」123456」;

string b=」123456」;

if(a==b)

console.writeline(「a equals to b」)

貌似也能說明引用型別比較相等的時候可以使用」==」,實際上

,在後面就能夠看到

,當使用」==」對引用型別變數進行比較的時候,

比較的他們是否指向堆上同乙個物件

.而上面

a,b指向的顯然是不同的物件

,只是物件包含的值相同

,所以可見,對於

string型別,

對他們的比較實際上比較的是值

,而不是引用

(string

是一種特殊的的引用型別

,它的特殊性在於它是不可變型別

,以後會說).

為了避免上面這些引起的混淆,

在物件判等部分將採用自定義的結構和類來分別說明

.簡單來說,

裝箱就是講乙個值型別轉換成等價的引用型別

.它的過程分為這樣幾步

:(1)在堆上為新生成的物件例項分配記憶體.

該物件例項包含資料

,但它沒有名稱

.(2)將棧上值型別變數的值賦值到堆上的物件中.

(3)將物件建立的物件的位址返回給引用型別變數.

因此,當我們執行這樣的**時:

int i=1;

object boxed=i;

console.writeline(「boxed point : 」+boxed);

效果如下圖所示:

(裝箱)

而拆箱則是將乙個已裝箱的引用型別轉換為值型別:

int i=1;

object boxed=i;

int j;

j=(int)boxed;

console.writeline(「unboxed point : 」+j);

需要注意的是拆箱操作分為兩步來完成:(1)獲取已裝箱的物件的位址.(2)將值從堆上的物件中複製到堆疊上的值變數中.可見,

拆裝箱需要反覆在對上進行操作,因此

,在程式中應該盡量避免無意義的拆裝箱

.

c 基礎 值型別和引用型別

c 中有兩種型別的資料,一種是值型別資料,一種是引用型別資料。首先說說什麼型別是值型別,例如 int float bool之類的基礎型別,以及用struct定義的型別,如 datetime。除此外,如string,陣列,以及用class定義的型別等都是引用型別。具體對比如下 值型別引用型別 記憶體分...

C 基礎 值型別和引用型別

struct型別 由一系列具有相同型別或不同型別的資料構成的資料集合 static void main string args struct person enmu型別 使用關鍵字const建立常量,建立常量時必須設定其初始值,一旦設定不允許修改。char只定義乙個unicode字元 string類...

C 基礎 值型別引用型別(十一)

值型別和引用型別 值型別包括 byte,short,int,long,char,float,double,bool,struct結構 引用型別包括 類型別,介面型別和陣列 等。值型別和引用型別特點 1.值型別的變數儲存的是原始值,即它代表的值本身。2.值型別不管是否賦值都會在棧記憶體中開記憶體。引用...