【问题标题】:Allocation of memory ( C++ ) Compile-time/Run-time?内存分配(C++)编译时/运行时?
【发布时间】:2011-09-10 13:31:06
【问题描述】:

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

我很好奇编译器如何在对象被构造之前(甚至在构造函数被调用之前!)为对象留出内存(内存分配)。

原始数据类型是如何发生的?

这听起来有点幼稚,但究竟是什么?

它完全是一个运行时进程,还是它(编译器)在运行时有任何计划,例如这样做这样做,这它在编译时期间事先决定。我完全不知道!

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

换句话说,从字面上看,任何类型的变量的内存分配是在什么时候发生的?在编译(或运行时)的哪一步?

【问题讨论】:

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


    【解决方案1】:

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

    对象成员的内存总是在构造函数运行之前就位。编译器及其运行时支持的工作就是确保这一点。

    【讨论】:

    • 静态变量可以在可执行文件本身中分配空间(然后内存映射到进程的地址空间),因此它们实际上是在编译时分配的。 :)
    • 感谢 david ... :) 但这会导致一个小问题。 内存分配内存预留!从你所说的,我明白两者是有区别的。你能给我解释一下吗? :)
    • @jalf 我已经忘记了。我已将静态变量添加到我称为保留而非分配的类别中。
    • 考虑堆栈上的变量,考虑一个 int 以供争论。编译器在编译时决定 int 相对于函数堆栈帧的位置。内存实际上是在调用函数之前由系统分配的,但是编译器在相对于函数的堆栈帧的已知位置保留了其中的一部分。所以我想说不同之处在于位置(至少相对于堆栈帧)在编译时是已知的。对于堆分配的 int,位置仅在运行时分配执行时确定。
    • 谢谢 david :) ...但我想详细了解它..你能给我一些链接或者我在谷歌上搜索有关该主题的准确信息吗? PS:我尝试了诸如“编译器内存问题”之类的短语,但没有多大用处!
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 我会说大部分本地对象的分配是在编译时完成的,因为编译器会发出机器代码,期望对象相对于当前堆栈帧处于特定偏移量,这个偏移量是在编译时决定的。
    【解决方案3】:

    有(粗略地说)三种典型场景:堆栈分配、堆分配和静态分配。

    首先是在函数中声明局部变量时发生的情况:

    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 的内存通常仍然在运行时分配,因为可执行文件加载。

    【讨论】:

    • 我怀疑静态分配“字面上”会占用可执行映像中的空间。想象一下全局 char buf[1000000]; 您的可执行文件不会增长 1MB,而是在加载时留出内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    相关资源
    最近更新 更多