2011-08-04 81 views
0

什麼是報表對象創建差異

int main() 
{ 
    A a = new A(); 
    A a; 
} 

2之差請解釋這兩對象創建語句。

+2

這功課嗎? – mjv

+0

如果你向我們解釋你的意思,那會更好。 – Woot4Moo

回答

3

第一個命令在棧上分配一個變量(A a),並在堆上初始化(new A())。

第二個只分配堆棧上的變量。它沒有被初始化,因此只有通過函數的返回值或調用類構造函數才能使用它,直到它被賦值爲止。


側面說明:當你的程序被編譯,並正在運行,它甚至不遠程像你寫的代碼。變量在你需要之前加載。你有上面的代碼將大致是這樣的:

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  8 (0x8) 
    .maxstack 1 
    .locals init ([0] class DERP.Program/A a, // This code here declares a local 
               // variable: A a; 
      [1] class DERP.Program/A b)  // another local variable: A b; 
    nop 
    newobj  instance void DERP.Program/A::.ctor() // This is: new A() 
    stloc.1       // this loads the new A() we created 
            // into A b; (stloc.1 means to store 
            // the last item we created into the 
            // local variable at index [1] 
    ret 
} // end of method Program::Main 

這沒關係,如果你不完全瞭解每種這些命令的是,但我曾評論它試圖使它作爲儘可能直接前進。因爲我們從未將A a分配給任何東西,所以它只是坐在本地堆棧上,閒逛,什麼都不做。我們不能使用它,因爲它不指向任何對象。


有許多不同的原因在代碼中,你可能會看到從實際分配分開的聲明。

例如,有時您需要聲明try {} catch {}子句之外的變量。讓我們說你的類在它的構造函數中取值。你有一個能夠從數據庫中獲取數據的函數。但是,由於其調用了數據庫,因此您希望捕獲該異常,並且如果拋出異常,則使用默認值初始化該類,而不是從DB調用返回的值。

由於道路作用域工作在C#中,try {} catch {}內聲明的變量是不是它的訪問之外,因此你需要在代碼聲明變量更早之前,你初始化它。

+0

您的陳述:「第二個只在堆棧上分配變量,它沒有被初始化,因此在你賦值之前不能使用它,要麼是函數的返回值,要麼是調用類構造函數。現在告訴我,如果用我的第二個對象A a調用函數,那該怎麼辦? a.Func();如果func不返回任何東西,那麼是否有可能使用它? –

+0

好吧,我明白了你的意思......謝謝 –

+0

不。如果你聲明瞭一個變量'A a',你*不能*以任何方式使用它,除了分配一些東西給它。 'a.Func()'會產生一個編譯錯誤,告訴你這個變量沒有被初始化。你需要做'A a = new A()'或'A a = SomeFunctionThatReturnsClassA()' –

2

A a = new A();

這將創建A類型的新對象。 a的值將是A的新實例。

A a;

這將只是一個聲明作爲一種類型的Aa的值將是null

0

第一個創建一個新的insatnce並將其分配給變量a

第二個不創建任何實例,所以anull

0

在第一條語句,將創建的類的一個新的對象實例和將被分配給一個變量

在第二聲明它是僅創建參考。

0

只有你的第一個聲明實際上創建了一個新的對象。第二個聲明只是在你的堆棧中分配了一個類型爲A的變量。

第一個在管理堆上創建一個新對象,在其上存儲在堆棧上創建的類型爲A的變量a上的引用。