2016-04-15 183 views
7

我想知道什麼時候應該在C++的堆棧上分配一個類?我在Java中擁有強大的背景,在Java中,所有類都使用關鍵字new在堆上分配。在C++中,我可以在堆棧和堆分配之間選擇,但現在已經引入了智能指針,分配所有不會將所有權轉讓給std::unique_ptr的所有權更有意義。C++堆棧與堆分配

我真的不能想到任何情況下,哪裏有必要或更好地使用堆棧分配。也許在嵌入式系統中進行某種優化?

+2

只是一個簡單的'std :: unique_ptr'是一個「堆棧」的對象。順便說一句,我們稱之爲自動和動態對象,因爲C++沒有堆棧或堆的概念。恕我直言,你想盡可能使用自動對象, – NathanOliver

+9

你通常使用相反的原則:如果動態分配是不必要的,你不這樣做。默認情況下的動態分配是「過早悲觀」。 – molbdnilo

回答

14

使用自動(堆)分配每當功能範圍 - 或一個控制塊的諸如forwhileif在函數內部等的範圍 - 是用於壽命對象需要的良好匹配。這樣,如果對象擁有/控制任何資源(如動態分配的內存,文件句柄等) - 它們將在析構函數調用期間被釋放,因爲該範圍被留下。 (當垃圾收集器停工時,不會在某些不可預測的情況下發生)。

只使用new,如果有一個明確的需求,如:

  • 需要的對象的生活比功能範圍較長,

  • 所有權移交給一些其他的代碼

  • 有一個指向基類的指針的容器,然後你可以進行多態處理(即使用虛擬調度到派生類函數實現),或者

  • 一個特別大的分配,將吃起來多的堆棧(你的OS /過程將有「協商」的限制,通常在1-8 +兆字節範圍)

    • 如果這是唯一的因爲您使用的是動態分配,並且您希望對象的生命週期與函數中的作用域綁定,所以您應該使用本地std::unique_ptr<>來管理動態內存,並確保無論您如何離開作用域,它都會被釋放:通過return,throw,break等。(您也可以使用std::unique_ptr<>中的數據成員class/struct來管理對象擁有的任何內存。)

馬修範NEVEL評論低於約C++ 11移動語義 - 的相關性的是,如果具有控制大量的動態分配(堆)存儲器,移動該堆棧上的小管理對象語義學授予額外的保證和對管理對象何時將其資源移交給其他代碼擁有的另一個管理對象(通常是調用者,但可能是某些其他容器/對象的註冊表)的細粒度控制。這種切換可以避免即時複製/複製堆上的數據。此外,elision返回值優化經常允許名義上自動/堆棧託管的變量直接在某些內存中構建,它們最終將被分配/返回,而不是在稍後複製。

+0

這是一個很好的總結。我最近重新編寫了一些將大量對象放入堆棧的代碼。如果你不小心,你可以在一個更大的程序中用完堆棧空間,或者使用深度遞歸。 –

+0

有關C++ 11移動語義的一些細節,答案將是完美的我認爲:upvote –

+0

好的總結,如果你添加什麼時候應該使用std :: unique_ptr而不是堆棧分配,我會給你答案打勾。 – KillerZefi

1

在大型代碼庫中,我們使用堆棧分配簡單結構對象,而對於更復雜的類(涉及多態性,內存所有權等),我們始終使用動態分配。