自由存储

  命名对象的生存时间由它的作用域(4.9.4节)决定。然而,能够建立起生存时间不依赖于建立它作用域的对象,这件事情也是很有用的。特别地,人们经常要建立起一些对象,希望在建立它们的函数返回之后还能够使用它们。运算符new将建立起这种对象,而运算符delete能用于销毁它们。由new分配的对象被说成是在“自由存储里的”(也说是“堆对象”或者“在动态存储中分配的”)。

  现在考虑我们可能如何按照写桌面计算器(6.1节)的方式写一个编辑器。语法分析函数可能去构造一个为代码生成器而用的表达式树

    struct Enode {
        Toekn_value oper;
        Enode* left;
        Enode* right;
        // ...
    };

    Enode* expr(bool get)
    {
        Enode* left = term(get);
        for(;;)
            switch(curr_tok){
            case PLUS:
            case MINUS:
            {
                Enode* n = new Enode;        // 在自由存储里建立一个Enode
                n->oper = curr_tok;
                n->left = left;
                n->right = term(true);
                left = n;
                break;
            }
            default:
                return left;                // 返回节点
            }
    }

代码生成器在此之后使用这些节点,而后销毁它们

    void generate(Enode* n)
    {
        switch(n->open){
        case PLUS:
            // ...
            delete n;        // 删除来自自由存储的Enode
        }
    }

由new创建的对象将一只存在,直到它被用delete显式地销毁为止。在此之后,由它所占用的存储就又能被new使用了。C++实现并不保证提供一个“废料收集器”,由它去找回不再存在的引用的对象并使它们占用的存储重新可以被new使用。因此,我将一只假定所有通过new建立的对象都需要手工地用delete释放。如果系统里提供了废料收集器,那么在大部分情况下的delete都可以省去(C.9.1节)。

  delete运算符只能用到由new返回的指针或者0,对0应用不会造成任何影响。

  还可以定义运算符new的特定版本(15.6节)。

🔚