2013-11-10 39 views
2

我有以下代碼,看起來用new創建一個引用是可以的,但是當涉及到用new創建一個對象時,它會崩潰,當我嘗試重新分配分配的內存時在C++中用new創建引用

float &f = *new float(1.3); 
delete &f; 
float f1 = *new float; 
delete &f1; 

我想知道區別,謝謝!

+0

引用不是指針。 – 2013-11-10 07:13:00

+0

感謝您的輸入,@ H2CO3,但似乎這裏的混淆是涉及多個操作。 'new'分配了一些內存並返回一個地址。例如。你可以用'new float'作爲一行,然後編譯它。下一部分,'* new float'將引用指針取消引用以獲取該地址的值。賦值是另一個操作,它與'new'操作符無關。該引用通過值(及其位置)初始化,而不是「新」。 – jozxyqk

+0

@jozxyqk這是因爲**引用不是指針。** – 2013-11-10 07:27:53

回答

0

首先,「用新創建引用」並不完全是你在做什麼。爲了理解這一點,需要進行破碎的代碼...

new float(1.3); 

此分配4個字節的存儲器,用於浮子,構建使用1.3雙恆定浮子,並且返回一個指向所述存儲器的開始 - 4個字節中的第一個。

*new float(1.3); 

由new操作符返回此「非關聯」的指針,因此,而不是讀指針值,你正在閱讀的4個字節的數據float它指向。

float &f = *new float(1.3); 

構造參考f,使用新提供的float。雖然(AFAIK)引用被實現爲具有編譯器優化潛力的指針(?),但這是人們抱怨的一部分。從概念上說,參考浮點數,你不應該假設你可以檢索地址,釋放內存,從而使得後面的參考無效。

然而,當你發現,它實際上是工作,你可以檢索地址...

&f 

在參考的位置產生一個指向內存,你可以再

delete &f; 

要回答您的實際問題...

float f1 = *new float; 

可以改寫如下

float f1; //a float on the stack! 
f1 = *new float; //should probably be: *new float(1.3) 

不初始化的基準,而是拷貝數據由新到浮子在棧上分配的。複製之後,new返回的內存地址永遠丟失 - 您已經「泄漏」了內存。

現在說明它爲什麼崩潰。

&f1; 

在堆棧上創建一個指向浮點數f1的指針。該內存尚未由new創建,或者新的內存分配庫最終使用。試圖釋放內存分配庫中不存在的內存地址...

delete &f1; 

...導致您的崩潰。

float &ffloat f1之間:一種是參考,作爲指針(其被假定從不改變)和一個是不參考其它存儲器堆棧上聲明一個實際的浮點變量內部實現。

什麼,你應該做的,而不是爲

float *f = new float(1.3f); 
// access f as *f = 1.2f or cout << *f 
delete f; 
+0

我最初的理解爲什麼delete&f崩潰是非法檢索從堆棧分配的內存使用刪除,應該是檢索只從堆分配的內存。經過您的切實解釋,我的想法是有道理的!謝謝! – BRYAN

1

考慮:

float f1 = *new float; 

它在自由存儲區創建float類型的對象,然後複製原始對象f1。你失去了原來的免費商店對象的地址,這給你一個即時內存泄漏。

該地址被傳遞給它們的所有存儲器解除分配函數的任務應該是相同的內存分配函數返回的一個,所以你最終的未定義行爲當你通過new沒有返回地址調用delete

請注意,未定義的行爲不會強制崩潰,但沒有崩潰並不意味着代碼中沒有任何問題。

+0

關於第一部分,看起來'&f'將產生與'new'返回的地址相同的地址。這是有保證的嗎? (不是說這應該完成,只是對引用的實現方式感興趣) – jozxyqk

+0

@jozxyqk:它不一樣。無論哪種情況,您最終都會將地址丟失到原始對象。 –

+0

所以你說'float&f = * new float(1.3);','&f'後面會返回一個不同的地址?我認爲它返回*相同的*地址,只是不確定它是有保證的。 – jozxyqk