6_在堆中创建对象

在堆中创建对象

我们可以在什么地方创建对象

  1. 全局变量区

    Person p; 比如把这个代码放到函数外面的时候, 就会在全局变量区域创建对象

  2. void Max()
    {
        Person p;
    }

    写到函数里面, 就是在堆栈中分配, 什么时候调用这个函数, 什么时候就创建对象, 一旦函数执行完毕, 这个对象的空间也就没有了.

  3. 堆, new delete

    在堆中创建对象 : Person* p = new Person();

    释放对象占用的内存 : delete p;

在堆中创建对象_

我们之前学到过一个函数 malloc(), 这个函数申请的空间就是在堆中分配的

我们可以通过 new 关键字来在堆中创建对象

语法是我们先定义一个 Person 类的指针, 然后 p 为指针的名字, 然后 new 后面跟上构造函数

Person 类定义如下:

class Person
{
    private:
        int x;
        int y;
    public:
        Person()
        {
            printf("Person()执行了\n");
        }
        Person(int x, int y)
        {
            printf("Person(int x, int y)执行了 \n");
            this->x = x;
            this->y = y;
        }
        ~Person()
        {
            printf("~Person()执行了\n");
        }
};

我们这里定义了两个构造函数, 如果你想使用无参数的, 就这样使用 : Person* p = new Person();

如果你想创建对象的时候给它赋值, 你可以选择使用第二个构造函数, 就像这样给它两个参数即可 : Person* p = new Person(1, 2);

在堆中申请内存, 一旦用完了之后, 需要把它释放出来, C 语言中是 free() 函数来释放内存, 在 C++ 中我们使用 delete 关键字释放对象空间

new delete 的本质

现在我们来看看 newdelete 两个关键字到底做了什么事情

通过运行结果猜测 : new 关键字除了在堆内存中申请空间创建对象之外, 还要调用它的构造函数, delete 关键字除了释放内存之外, 还要调用它的析构函数

现在我们看汇编代码观察一下, new 先调用了 windows 提供的 HeapAlloc 申请了一块内存, 然后调用了它的构造函数, 结论就是 new 这个关键词相当于就是 malloc 函数加上构造函数

delete 请自行分析

new[] / delete[]

如果你要在堆中申请一个数组, 你就需要使用 new[] 关键字

  1. 用 C 和 C++ 的方式分别在堆中申请一个 int 数组:

    C : int* p = (int*)malloc(sizeof(int)*10); free(p);

    C++ : int* p = new int[10]; delete(p);

  2. 分别用 C 和 C++ 在堆中申请 Class 类型数组:

    C : int* p = (Person*)malloc(sizeof(Person)*10); free(p);

    C++ : Person* p = new Person[10]; delete[] p;

基本类型两种是没有区别的, 如果你是定义的是自己的类的话, 这两种方式是有区别的

malloc 函数方式申请 Class 类型数组, 仅仅是给我们分配空间, 并不会调用构造函数, new 关键字不光是在堆中申请十个对象的空间, 对于每个对象, 它都会调用一次构造函数

同样, free 方式是只管释放空间, 并不会调用析构函数, delete 方式不光释放空间, 还会调用析构函数.

  • delete 和 delete[] 有什么区别 ?

Person* p = new Person[10];

delete p;

比如说这样我创建的是十个对象, 但是我删除的时候没有加中括号, 我们运行观察汇编发现, 只有一个析构函数执行了, 并且程序出错了

区别就出来了, 如果你不加中括号的话, 它最后只删除第一个对象, 只调用第一个对象的析构函数

简单总结 : 如果我们只创建一个对象, 我们可以创建的时候使用 new, 删除的时候使用 delete; 如果你要创建多个对象, 比如创建一个对象数组, 那么创建的时候应该是用 new[], 删除的时候使用 delete[].