内存分配(C ++)编译时/运行时?

时间:2011-09-10 13:31:06

标签: c++ memory compiler-construction constructor compilation

我不确定这个问题有多合适,但是 -

我很好奇编译器在构造对象(内存分配)之前是如何设置内存的(甚至在构造函数被调用之前!)

原始数据类型如何发生?

这听起来有点天真,但具体到底是什么?

它是完全是一个运行时进程,还是它(编译器)在运行时有任何计划,比如执行此操作来执行此操作,它在编译时期间事先决定。我根本不知道!

  

对象,无论是原始类型,指针还是大类的实例,都占用一定的已知内存量。那个记忆必须以某种方式留给对象。在某些情况下,初始化该预留内存。初始化是构造函数的作用。它们不会留出(或分配)存储对象所需的内存。该步骤在调用构造函数之前执行。

换句话说,就时间而言,什么样的变量的内存分配何时发生呢?编译(或运行时)中的哪一步?

3 个答案:

答案 0 :(得分:7)

内存分配总是在运行时发生。对于驻留在堆栈上的对象或静态变量,内存保留在编译时(或在C99 VLA的运行时)发生。

在构造函数运行之前,对象的成员的内存始终存在。编译器及其运行时支持的工作是确保如此。

答案 1 :(得分:2)

使用newnew[]或某些变体创建的分配对象在运行时完成,方法是在构造函数运行之前访问freestore并找到足够的空间放置新对象。

函数内的本地对象的分配在运行时完成。但是,这通常通过将堆栈指针移动到正确的字节大小来实现,并且现在为该对象保留先前值和新值之间的空间。构造函数在空间运行后运行。

全局和静态对象的分配由编译器在编译时完成,并且它们的构造函数在加载它们的转换单元时运行(通常在main()开始执行之前)。

在另一个对象中直接包含(不是通过指针)对象的分配是作为该对象分配的一部分完成的。

答案 2 :(得分:2)

(松散地说)有三种典型的场景:堆栈分配,堆分配和静态分配。

第一个是在函数中声明局部变量时会发生什么:

void foo ( )
{
   int bar = 42;
}

此处,bar的内存分配在stack上。它是在调用foo时分配的。

使用new运算符创建类实例时会出现第二种情况:

void foo ( )
{
    MyClass* bar = new MyClass( );
}

此处,i的内存分配在heap上。这在运行时再次发生,并在new运算符执行时发生。如果您对此更熟悉,它的工作方式基本上与C malloc相同。

最后,还有静态分配。

void foo ( )
{
    static int bar = 42;
}

这里,编译器提前知道bar需要内存,因此它会向可执行文件中插入一条指令,告诉可执行加载程序保留空间,或者在可执行文件中为字节创建一个空格。因此,bar的内存通常仍然在运行时分配,因为可执行文件会加载。