11. new & delete

new / delete

new int;
new Stash; //new一个类, 分配空间之后,调用构造函数.
new int[10];

delete p; //先调用析构函数,再释放空间
delete[] p; //

new带着[],则delete也带着[].

eg:
int* psome = new int[10];
new 10个int空间,交给psome指针.
delete [] psome;
带[]释放,因为[]告诉some指的是很多东西. 带[] 将调用很多个析构.
若不带[]释放,空间会被回收,但是告诉psome所指的对象只有一个,只会调用一个析构.

new过程

eg:
int *p = new int;
int *a = new int[10];
Student *q = new Student;
Student *r = new Student[10];

(1). 在C++的运行库实现了new过程(前提是空间不是很大),否则则需要
找操作系统要内存.
(2). int *p = new int; 在堆里寻找一块合适的空间,在这个空间放int, 指针p指向这个int. 同时有一张表产生,表会记录申请的内存地址和内存大小(字节为单位).
int *a = new int[10]; ……
Student *q = new Student;……
Student *r = new Student[10];……
这里写图片描述

delete过程

delete p;
p的地址在表中查找,在不在里面. 如果在,则把相应内存大小收回.
同时把表也删除了.
a++;
delete [] a; //在表中找不到a的地址, 程序运行出错.
delete q; //先析构,在空间回收
首先调用析构, 如何知道调用Student的析构呢?
原始:q的类型知道, 编译知道,编译时会插入调用析构的语言.
delete r; //调用一个析构,然后资源回收
delete[] r; //调用多个析构,然后资源回收

#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
private:
    int i;
public:
    A() 
    { 
        i = 0;  
        cout << "A::A()" << endl; 
    }
    ~A() 
    {
        cout << "A::~A(), i = " << i << endl; 
    }
public:
    void set(int i)
    {
        this->i = i;
    }
    void f() { cout << "hello"; }
};


int main()
{
    A* p = new  A[10]; //先申请内存,然后调用构造函数
                       //A::A()10次
    for (int i = 0; i < 10; i++)
    {
        p[i].set(i);
    }
    delete p; //先调用构造函数,由于没有[],则只调用一次
              //A::~A(), i = 0
     //Visual Studio报错:触发一个断点
    return 0;
}
#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
private:
    int i;
public:
    A() 
    { 
        i = 0;  
        cout << "A::A()" << endl; 
    }
    ~A() 
    {
        cout << "A::~A(), i = " << i << endl; 
    }
public:
    void set(int i)
    {
        this->i = i;
    }
    void f() { cout << "hello"; }
};


int main()
{
    A* p = new  A[10]; //先申请内存,然后调用构造函数
                       //A::A()10次
    for (int i = 0; i < 10; i++)
    {
        p[i].set(i);
    }
    delete[] p; //先调用构造函数,调用10次,并且顺序是颠倒的
              //A::~A(), i = 9
              //A::~A(), i = 8
              //A::~A(), i = 7
              //A::~A(), i = 6
              //A::~A(), i = 5
              //A::~A(), i = 4
              //A::~A(), i = 3
              //A::~A(), i = 2
              //A::~A(), i = 1
              //A::~A(), i = 0                    
    return 0;
}

建议

  1. 不要用delete释放不是new申请的空间
  2. 不要2次释放同一个空间
  3. new带[],delete带[]
  4. new不带[], delete不带[]
  5. delete null pointer是安全的
int main()
{
   int *p = 0;
   delete p; //这种写法是安全的
   return 0;
}
#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
  private:
    int i;
    int *p; //定义成员变量指针
  public:
    A()
    {
        p = 0; //构造函数指针为空
        i = 0;
        cout << "A::A()" << endl;
    }
    ~A()
    {
        if(p)
         delete p; //析构函数delete
        cout << "A::~A(), i = " << i << endl;
    }
public:
    void set(int i)
    {
        this->i = i;
    }
    void f() { p = new int; } //成员函数内,new
};

//new了之后,程序不delete,程序没问题.
//原因:现在的操作系统都是多进程操作系统,程序每一次运行时新的进程,这个程序起来,操作系统分配空间,4G蓄奴空间。进程结束空间就会回收.
//但是程序一直要跑的,eg:手机的程序。内存泄漏
int main()
{
    A a;                   
    return 0;
}

注意事项

若类的成员变量有指针, 成员函数里new, 则需要在构造函数中p =0, 析构函数中if(p) delete p;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值