编译器:如何编译类实例化代码?

时间:2016-08-03 05:03:08

标签: c++ compiler-construction runtime interpreter jit

假设我们(在C ++中):MyClass* x = new MyClass(10)

有人可以解释当编译器解析此语句时会发生什么'确切'吗? (我试着看看红龙书,但找不到任何有用的东西)。

我想知道堆栈/堆或编译器的符号表中发生了什么。编译器如何跟踪x变量的类型?以后对x->method1(1,2)的调用将如何解析为MyClass中的适当方法(为简单起见,假设没有继承,MyClass是我们唯一的类。)

2 个答案:

答案 0 :(得分:2)

MyClass* x是指向MyClass类型的对象(实例)的指针的定义。该变量的内存根据其定义的位置进行分配:如果在方法中定义,并且是局部变量,则使用堆栈。它是存储地址的内存。

然后,表达式new MyClass(10)是一个命令,用于在堆中为对象(实例)本身分配内存,并将返回地址存储在x中。要填充新对象MyClass的内存(设置其初始状态),将自动执行特殊方法(至少一个) - 构造函数(在某些情况下为几个) - 在示例中接收值10

因为C ++允许继承(这也是在创建实例时执行几个构造函数的原因),所以有一些机制来确定应该精确调用哪个方法。你应该阅读关于Virtual method table的某个地方。

在最简单的情况下(没有继承),变量类型x(指向类型MyClass的对象的指针)提供有关对象结构的所有必要信息。因此,x->method1(1,2)(*x).method1(1,2)调用成员method1来执行参数12(存储在堆栈中)以及形成的数据对象的状态(存储在堆中)并由this指针在类的任何非静态成员内部提供。当然,方法本身并不存储在堆中。

<强>更新

您可以通过示例进行相同的实验,例如:

#include <iostream>
#include <string>
using namespace std;

class MyClass
{
private:
    int innerData;
    long long int lastValue;
public:
    MyClass() // default constructor
    {
        cout << "default constructor" << endl;
        innerData = 42;
        lastValue = 0;
    }
    MyClass(int data) // constructor with parameter
    {
        cout << "constructor with parameter" << endl;
        innerData = data;
        lastValue = 0;
    }
    int method1(int factor, int coefficient)
    {
        cout << "Address in this-pinter " << this << endl;
        cout << "Address of innerData " << &innerData << endl;
        cout << "Address of lastValue " << &lastValue << endl;
        cout << "Address of factor " << &factor << endl;
        lastValue = factor * innerData + coefficient;
        return lastValue;
    }
};

int main(void)
{
    MyClass* x = new MyClass(10);
    cout << "addres of object " << x << endl;
    cout << "addres of pointer " << &x << endl;
    cout << "size of object " << sizeof(MyClass) << endl;
    cout << "size of pointer " << sizeof(x) << endl;
    x->method1(1, 2);
}

答案 1 :(得分:1)

C ++确实有点讨厌,这已经在C中开始了。只需看看前3个令牌:MyClass * x。编译器必须查找MyClass以确定这是而不是乘法。由于它是一种类型,它也不应该查找x,而是将x添加到符号表中(实际上不能延迟)。在理想的简单解析语言世界中,没有必要为解析的每个标记保持符号表的最新状态。

x的定义之后,=表示初始化表达式。这是一个很容易解析的问题:new明确地是一个关键字,它不是展示位置new,而且正在创建的类型就在那里。