2010-10-21 66 views
2

Circle是一個類,公共方法爲GetDiameter()。 下面兩組代碼有什麼區別?用C++在堆或棧上創建變量

的Qn1:是否方法1(因此不需要空閒內存)分配用於c存儲器,而方法2(無需手動釋放內存)分配用於c存儲器?

Qn2:什麼時候應該使用方法1或方法2?

方法1:

void Init() 
{ 
Circle c; 
c.GetDiameter(); 

return; 
} 

方法2:

void Init() 
{ 
Circle *c = new Circle(); 
c->GetDiameter(); 

return; 
} 
+0

你是怎麼知道的? :) – ruslik 2010-10-21 12:56:16

+0

我懷疑它。只是想確認一下。 – seveleven 2010-10-21 12:59:04

回答

10

作爲良好編碼實踐的一般規則,應儘可能使用方法1。 僅當您需要在不同位置存儲和/或共享指針時才應使用方法2。所有在方法或類中僅在本地使用的對象應放入堆棧中。

+1

小調:異常是巨大的對象,sizeof(SomeClass)與整個堆棧大小相當。 – valdo 2010-10-21 14:37:01

2

是,方法1個分配對堆棧,因此沒有必要釋放,其中作爲堆方法2個分配其必須被釋放。

  1. 使用堆棧,如果你不想要的功能
  2. 使用堆結束後的對象,如果你想保留的對象活着的功能的退出也後(前提是您保留分配的地址)
+1

啊,但'Circle :: operator new()'可能會被覆蓋以使用'alloca()'來分配堆棧內存。但實例仍然需要被「刪除」。我愛C++ :) – 2010-10-21 13:00:14

+0

@Frédéric:我不認爲這實際上是允許的。在編譯時,結果幾乎肯定是未定義的,因爲'operator new'被定義爲對具有動態存儲持續時間的對象執行分配。 'alloca()'不返回指向具有動態存儲持續時間的內存的指針。然而,符合'operator new'的重載可能總是拋出'bad_alloc';雖然... – 2010-10-21 13:34:22

+0

你說的那些「允許」或「未定義」或「符合」的東西是什麼?如果它編譯,我們將發佈它,pronto;) – 2010-10-21 13:52:20

6

使用方法2時:

  • 對象的壽命超過了功能的 或
  • 當調用一些函數,返回指針,即要創建來自物體的範圍的抽象工廠或類似工廠。

後一種技術通常用於處理多態性,所以您得到的類型實際上可能不是指針的類型,而是從它派生的類。

無論何時您需要刪除返回值,最好通過將其封裝在智能指針或其他會自動銷燬的對象中進行處理。

如果在函數結束時要做清理工作,理想情況下應該使用自動對象(如scoped_ptr或auto_ptr)來完成。這可以確保即使函數儘早終止,清理也會發生(例如拋出異常)。這種技術被稱爲RAII - 資源獲取是初始化。

+1

+1,還注意到一個新的縮寫SBRM(Scoped Bound Resources Management)是RAII的同義詞,但名稱更清晰。 – 2010-10-21 14:25:56

1

方法1:在堆棧上分配內存。方法2:在堆上分配的內存。 + 作爲一般規則,如果您使用call'new',則必須調用'delete'來釋放內存。

2

上堆與棧我見過的最好的討論,一個是在這裏:heap vs. stack(向下滾動到討論中)

簡短的摘要:

  • 棧:對象的生命週期是由編譯器
  • 控制
  • 堆:對象的生存期由程序員
  • 0

    堆棧

      控制
    • 限定和固定大小
    • Stricked最後在入先出對象的生存期(通常限於封閉函數)

    • 尺寸通常僅由系統存儲器的大小受限
    • 手動管理對象的使用壽命

    這意味着對於只有短壽命的理想小物體。對於大對象或具有比創建函數更長的生命週期的任何對象,都需要堆。手動對象的生命週期意味着如果你不小心的話,你可以開發內存泄漏。

    1

    你甚至還沒有開始使用指針,方法2已經有內存泄漏。

    +0

    Yikes,這個^^^ – rossb83 2016-12-20 22:38:39