首页 > 编程笔记 > C++笔记 阅读:102

C++ new和delete的用法(附带实例)

C++ 程序中定义一个变量后,其值会被放入内存中。读者是否好奇,变量的值到底被存放在哪里?

如果开发者未向系统申请动态内存,变量的值将会被放入栈中。在栈中,变量占用的内存大小是无法改变的,它们的占用与释放与变量定义的位置和储存方式有关。

与栈相对应,堆是一种动态内存。当开发者向系统申请了动态分配内存,该变量将会被放入堆中。根据需要,这个变量的内存大小可以改变,内存申请和释放的时机由开发者操控。

C++ 中,new 用于申请动态堆内存空间,delete 用于释放动态堆内存空间。

使用 new 关键字申请堆内存空间的方式如下:
p1 = new type; // 使用 new 关键字申请堆内存,并将指针 p1 指向它
其中,p1 表示指针,new 是关键字,type 是类型名。new 返回新分配的内存单元的地址。

【实例 1】动态分配空间。定义一个指针变量,通过 new 关键字为其分配内存空间,代码如下:
#include <iostream>
using namespace std;
int main()
{
    int *p1 = NULL; // 定义指针 p1
    p1 = new int; // 申请一块动态内存(堆),p1 指向它
    *p1 = 111; // 将 111 存入堆内存空间
    cout << "p1 内存的内容" << *p1 << "," << p1 << "所指向的地址" << p1 << endl;

    int *p2;
    int k;
    p2 = &k;  // 为变量 k 分配栈内存,p2 指向它
    *p2 = 222; // 分配内存后方可赋值
    cout << "p1 内存的内容" << *p2 << "," << p2 << "," << p1 << endl;
    return 0;
}
可以看到,指针 p1 创建后申请了动态分配,程序自动分配给它一块堆内存。而指针 p2 则获取了栈中的内存地址,属于静态分配。

程序运行结果为:

p1 内存的内容111,0x161510所指向的地址0x161510
p1 内存的内容222,0x6ffdfc,0x161510


动态分配方式虽然灵活,但也带来了新的问题。开发者申请堆内存后,这块内存将由开发者掌握,也就是说系统无法自动释放它,只有开发者使用 delete 关键字才能将其回收。

【实例 2】释放内存。使用 new 关键字分配内存,用完之后进行释放,输出分配内存的地址以及释放内存之后的地址,具体代码如下:
#include <iostream>
using std::cout;
using std::endl;

int *newPointerGet(int *p1) // 定义函数 newPointerGet()
{
    int k1 = 55;
    p1 = new int; // 申请一块动态内存(堆),p1 指向它
    *p1 = k1; // 将 k1 存入堆内存空间
    return p1;
}

int *PointerGet(int *p2) // 定义函数 PointerGet()
{
    int k2 = 55;
    p2 = &k2; // p2 表示的栈内存中存放 k2,此内存在函数执行后会被系统销毁
    return p2;
}

int main()
{
    cout << "输出函数各自返回指针所指向的内存的值" << endl;
    int *p = NULL;
    p = newPointerGet(p); // p 具有堆内存的地址
    int *i = NULL;
    i = PointerGet(i); // i 具有栈内存地址,内存内容被销毁
    cout << "newGet: " << *p << "," << p << endl;
    cout << "i 所指向的内存没有被立刻销毁,执行一个输出语句后:" << endl;
    cout << "iGet: " << *i << "," << i << endl; // 仍然为 55,但不代表程序不对它进行销毁
    delete p; // 执行其他语句后,程序销毁了栈空间
    cout << "销毁堆内存后:" << endl;
    cout << "p: " << *p << endl;
    return 0;
}
程序运行结果为:

输出函数各自返回指针所指向的内存的值
newGet: 55,0xba1510
i 所指向的内存没有被立刻销毁,执行一个输出语句后:
iGet: 0,0x6ffdcc
销毁堆内存后:
p: 12196368

变量 p 接受了 newGet 返回的指针的堆内存地址,所以内存的内容并没有被销毁,而栈内存则由系统控制。程序最后使用 delete 语句释放堆内存。

相关文章