我不确定这个问题有多合适,但是 -
我很好奇编译器在构造对象(内存分配)之前是如何设置内存的(甚至在构造函数被调用之前!)。
原始数据类型如何发生?
这听起来有点天真,但具体到底是什么?
它是完全是一个运行时进程,还是它(编译器)在运行时有任何计划,比如执行此操作,来执行此操作,它在编译时期间事先决定。我根本不知道!
对象,无论是原始类型,指针还是大类的实例,都占用一定的已知内存量。那个记忆必须以某种方式留给对象。在某些情况下,初始化该预留内存。初始化是构造函数的作用。它们不会留出(或分配)存储对象所需的内存。该步骤在调用构造函数之前执行。
换句话说,就时间而言,什么样的变量的内存分配何时发生呢?编译(或运行时)中的哪一步?
答案 0 :(得分:7)
内存分配总是在运行时发生。对于驻留在堆栈上的对象或静态变量,内存保留在编译时(或在C99 VLA的运行时)发生。
在构造函数运行之前,对象的成员的内存始终存在。编译器及其运行时支持的工作是确保如此。
答案 1 :(得分:2)
使用new
或new[]
或某些变体创建的分配对象在运行时完成,方法是在构造函数运行之前访问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
的内存通常仍然在运行时分配,因为可执行文件会加载。