2015-07-20 57 views
0

我有一個理論上的問題比實際更多,因爲我只想知道在某種情況下會發生什麼,而不是什麼實際情況。因此,例如,如果我創建了一個智能指針對象std::uniqe_ptr<City> smallville(new City);,然後在該對象內創建對象,如Building b1; Building b2;這些對象是否仍會在堆上創建,即使語法是用於在堆棧上創建它們的?或者使用智能指針創建更多對象會更好嗎?堆上的對象

+0

你能舉出完整的例子嗎? –

+3

你是什麼意思的「在我創造物體的對象內」,是城市的b1和b2成員? (在這種情況下,當你創建一個「新城市」時,它們會在堆上創建)。它們是函數中的局部變量嗎? (在這種情況下,它們被創建在堆棧上,當你離開函數時消失,因此指向它們是不正確的) – BrunoLevy

+0

@NO_NAME一個例子就是我試圖用b1和b2作爲smalliville的成員來描述的。 – jonjohnson

回答

4

讓我們看一下簡單的例子:

class B{ 
    long b; 
}; 

class A{ 
B b; 
int a; 
}; 

如果你聲明在棧上,像這樣:

A a; 

對象將完全與連續字節堆棧聲明。

如果我們聲明堆上,就像這樣:

A* a = new A(); 

對象將完全與連續字節堆聲明。

您使用智能指針的事實不會改變此行爲,所有內容都將在堆中聲明。智能指針只能用取消分配機制包裝原始指針。

如果我們採取這一步,我會說智能指針不會改變分配機制。讓我們看看下面的例子:

class C{ 
    int* c; 
public: 
    C(void* buffer) : c(new (buffer) int(5)){} 
}; 

int main(){ 
    char stackBuffer[100]; 
    unique_ptr<C> c = std::make_unique<C>(stackBuffer); 
} 

在這裏,C的構造函數獲取一些緩衝區來分配一個整數。 std :: unique_ptr沒有改變分配機制,儘管C是從堆中分配的,但仍然是從堆棧中分配的緩衝區中分配整數。

或更簡單:

class E{}; 

int main (void){ 
     char buffer [100]; 
     unique_ptr<E> c(new(buffer) E()); 
}; 

unique_ptr只裹着通過new運算符的指針。 new從堆棧中的緩衝區中分配了對象。 您可能會對所有這些示例感到困惑,但答案仍然很簡單 - 智能指針會保留您提供的分配機制。像我一樣沒有任何placement new,對象將從堆中有效地分配,而不管它是否包含內部對象。所有這些將在堆上宣佈。如果你提供不同的分配機制 - 智能指針會保留它。再次,它的全部任務是用相關的析構函數封裝原始指針,該析構函數將取消分配內存。與你所謂的「在棧上」語法(自動壽命,而不是在動態壽命堆分配對象的)宣佈

0

對象是圍繞它們的對象或範圍,並且它們的壽命的物理部分綁在一起。因此,如果您在堆棧中分配一個對象(函數體中的Foo foo;),則此對象及其所有自動子對象都將位於堆棧上。

在全局範圍內聲明的對象像最大生命期自動對象(與程序本身一樣),但實際存儲在靜態內存中。

如果你在堆上分配一個對象,它的所有自動子對象也將與它一起生活在堆上。

注意:這不是C++標準的一部分(只有生命週期和範圍在那裏定義),但這在實踐中發生在「常規」實現中。

0

smallville在棧上,但是smallville指向的新對象在堆上。

1

如果b1b2City類然後將它們放置在被分配用於City的內存塊中的非靜態成員 - 將有任何種沒有單獨的分配。

如果b1b2當地人在City的方法之一,那麼這種情況是沒有什麼不同,任何功能,他們將被放置在堆棧上。

當然,如果Building通過new在其ctor中進行任何分配,那麼分配的這些對象是堆中的獨立塊。

0

「在棧上創建它們(建築物)的語法是什麼?」 Building b1上下文不足。這將在周圍環境中創建對象。如果周圍的上下文是一個函數,那麼該建築物將具有函數範圍(「在堆棧上」)。如果周圍的上下文是一個類,那麼這些對象將是類成員。如果沒有周圍的環境(除了程序本身),該對象將是一個全局的並且在該程序的整個生命週期中存在。