堆上的对象

时间:2015-07-20 07:39:59

标签: c++ unique-ptr

我有一个理论上的问题而不是实际问题,因为我只想知道在某种情况下会发生什么,而不是任何实际情况。因此,例如,如果我创建一个智能指针对象var componentA = require('./componentA'); var componentB = require('./componentB'); var navigationComponents = [componentA, componentB]; render() { return( <div> _.map(navigationComponents, Component) { return <Component />; } </div> ) } ,然后在该对象内创建像std::uniqe_ptr<City> smallville(new City);这样的对象,那么这些对象是否仍会在堆上创建,即使语法是用于在堆栈上创建它们?或者使用智能指针创建更多对象是否更好?

5 个答案:

答案 0 :(得分: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的情况下,无论对象是否包含内部对象,都将从堆中分配出来。所有这些都将在堆上声明。如果你提供不同的分配机制 - 智能指针将保留它。再一次,它的整个任务是用相关的析构函数包装原始指针,该析构函数将取消分配内存。

答案 1 :(得分:1)

如果b1b2City类的非静态成员,那么它们将被放置在为City分配的内存块中 - 将会有没有任何单独的分配。

如果b1b2是其中一个City方法中的本地人,则该情况与任何函数没有区别,它们将被置于堆栈中。< / p>

当然,如果Building在其ctor中通过new进行任何分配,那么分配的对象就是堆上的单独块。

答案 2 :(得分:0)

使用您所谓的“on the stack”语法声明的对象(自动生存期,而不是堆分配对象的动态生存期)实际上是它们的封闭对象或范围,它们的生命周期是紧密相连的。

因此,如果在堆栈中分配一个对象(函数体中为Foo foo;),则该对象及其所有自动子对象将存在于堆栈中。

在全局范围内声明的对象就像最大生命周期的自动对象(与程序本身相同),但物理存储在静态内存中。

如果在堆上分配一个对象,它的所有自动子对象也将与它一起存在于堆中。

注意:这不是C ++标准的一部分(只有生命周期和范围在那里定义),但实际上在“通常”实现中会发生这种情况。

答案 3 :(得分:0)

smallville正在堆叠,但是Smallville指向的新对象是Heap。

答案 4 :(得分:0)

“在堆栈上创建它们(建筑物)的语法是什么?” Building b1背景不足。这将在周围的上下文中创建对象。如果周围的上下文是一个函数,那么构建将具有函数作用域(“在堆栈上”)。如果周围的上下文是一个类,那么对象将是类成员。如果没有周围的上下文(除了程序本身),该对象将是一个全局的,并且在该程序的生命周期中存在。