生产编译器如何在流控制上实现析构函数处理

8 c++ compiler-construction oop destructor flow-control

长话短说 - 我正在编写一个编译器,并且达到了OOP功能,我面临着涉及处理析构函数的两难问题.基本上我有两个选择:

  • 1 - 将所有析构函数放在程序中该点需要调用的对象上.这个选项听起来像是性能友好且简单但会使代码膨胀,因为根据控制流程,某些析构函数可以多次复制.

  • 2 - 每个代码块的分区析构函数,带有标签和"意大利面条跳转",只能通过所需的代码.好处 - 没有析构函数将被复制,缺点 - 它将涉及非顺序执行和跳转,以及额外的隐藏变量和条件,这将需要例如确定执行是否留下块以继续在父级执行阻止或中断/继续/转到/返回,这也增加了它的复杂性.额外的变量和检查很可能会占用这种方法所节省的空间,具体取决于对象的数量以及内部复杂的结构和控制流程.

而且我知道对这些问题的通常反应是"做两件事,分析和决定",如果这是一项微不足道的任务,那就是我要做的事情,但编写一个功能齐全的编译器已经证明有些艰巨,所以我更喜欢得到一些专家意见而不是而不是建造两座桥梁,看看哪座桥梁做得更好,又烧掉另一座桥梁.

我把c ++放在标签中,因为这是我正在使用的语言,并且我对它和RAII范例有点熟悉,这也是我的编译器正在建模的内容.

Mat*_*son 2

我不知道商业编译器如何得出代码,但假设我们此时忽略异常 [1],我将采取的方法是调用析构函数,而不是内联它。每个析构函数将包含该对象的完整析构函数。使用循环来处理数组的析构函数。

内联调用是一种优化,除非您“知道它有回报”(代码大小与速度),否则您不应该这样做。

您将需要处理“封闭块中的破坏”,但假设您没有跳出块,那应该很容易。跳出块(例如 return、break 等)意味着您必须跳到一段代码来清理您所在的块。

[1] 商业编译器有基于“异常在哪里抛出”的特殊表,以及生成的一段代码来执行清理 - 通常通过在每个清理块中具有多个跳转标签来对许多异常点重复使用相同的清理。