c++操作符的内部工作原理

c++ operator new how this works internally

本文关键字:工作 内部 操作符 c++      更新时间:2023-10-16

例如我有一个简单的代码:

class B
{
};
class A
{
    B b;
    public:
    A()
    {
        throw 1;
    }
};
int main()
{
    A* a = 0;
    try
    {
        a = new A;
    }
    catch (int)
    {
    }
}

构造函数A抛出异常,则不会调用析构函数。但是B的析构函数会被调用。堆中的内存将不会被分配。我的问题是这是如何在内部工作的?首先是什么:构造A还是在堆中分配内存?那么,如果分配是第一位的,那么在出现异常时如何处理分配呢?否则,如果构造A是第一个,它是如何复制到堆的?

  1. 内存分配完成。
  2. 调用A的构造函数
  3. A的构造函数调用b的构造函数 A的构造函数抛出。作为标准异常处理过程的一部分,B的析构函数被称为(工作中的RAII)。
  4. 堆栈unwind到调用者(main)。
  5. 内存被释放(因为对象没有成功构造)。
没有调用A的析构函数,因为对象没有完全构造。但是,已完全构造的成员仍然被销毁。

内存被自动释放,就像控制离开块时局部变量被销毁一样。如果您熟悉Java和/或c#,可以将其视为不可见的try-finally结构。或者一系列这样的结构

先做什么:构造A还是在堆中分配内存?

除非有内存,否则没有空间可以构造对象。内存分配总是优先;然后代码继续进行初始化。这适用于所有类型的内存分配,而不仅仅是动态的,因为构造函数在开始初始化对象之前需要有一个有效的this地址。

如果分配是第一位的,如果出现异常,如何处理分配?

编译器发出特殊的代码来处理这里的"魔法"。这段代码将为所有基类和成员(如B)运行析构函数,这些成员在代码进入A的构造函数时已经完全构造好了。