2015-07-20 61 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上下文不足。这将在周围环境中创建对象。如果周围的上下文是一个函数,那么该建筑物将具有函数范围(“在堆栈上”)。如果周围的上下文是一个类,那么这些对象将是类成员。如果没有周围的环境(除了程序本身),该对象将是一个全局的并且在该程序的整个生命周期中存在。