当前课程知识点:C++语言程序设计基础 > 第6章 数组、指针与字符串(二) > 动态内存分配 > 动态分配与释放内存
动态内存分配
动态申请内存操作符 new
new 类型名T(初始化参数列表)
功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。
结果值:成功:T类型的指针,指向新分配的内存;失败:抛出异常。
释放内存操作符delete
delete 指针p
功能:释放指针p所指向的内存。p必须是new操作的返回值。
例6-16 动态创建对象举例
#include <iostream>
using namespace std;
class Point {
public:
Point() : x(0), y(0) {
cout<<"Default Constructor called."<<endl;
}
Point(int x, int y) : x(x), y(y) {
cout<< "Constructor called."<<endl;
}
~Point() { cout<<"Destructor called."<<endl; }
int getX() const { return x; }
int getY() const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
int main() {
cout << "Step one: " << endl;
Point *ptr1 = new Point; //调用默认构造函数
delete ptr1; //删除对象,自动调用析构函数
cout << "Step two: " << endl;
ptr1 = new Point(1,2);
delete ptr1;
return 0;
}
运行结果:
Step One:
Default Constructor called.
Destructor called.
Step Two:
Constructor called.
Destructor called.
大家好
欢迎回来继续学习
C++语言程序设计
这一节我们来学习
动态内存分配
在此之前呢
我们都是在写程序的时候
计划好
在这个程序中呢
我们要用到哪些数据
需要多少存储空间
需要开多大的数组
然后预先在程序中
都定义好
但是呢
已经有同学在写程序中
遇到困难了
说我不知道我要处理的数据规模
有多大呀
我也不知道这个数组开多大合适
是不是我就尽量开大一点呢
如果大的不太多还可以
如果你完全不知道
数据规模有多大
那么你尽量开大一点
大多少
给数组分配了太大的存储空间
势必造成内存单元的浪费
所以有的时候呢
我们要程序运行起来
才能够确定
这一次运行
我们需要处理的数据规模有多大
我开一个数组要开多大
那么
也有同学问了
老师 我能不能用变量来确定
数组元素的个数呢
用我们原来学的
这种数组定义方式
那么数组元素个数
是不能够用变量来表示的
但是我们也有办法
在运行时确定数组要多大
那么这个数组呢
就必须在运行过程中
用动态内存分配的方式
去获得空间
实际上在前面我们讲
指针的时候
有很多同学已经觉得
不喜欢这个指针
这个指针没用
老师总是讲
你可以用变量来访问内存空间
也可以用指针里面存放的地址
来访问内存空间
你可以用数组名去访问数组元素
你还可以用指针访问数组元素
那很多同学说为什么呀
有变量名就挺好了
够用了
有数组名访问数组元素就够用了
干吗我们还需要用指针
去访问它们呢
那么学了这一节
大家也会得到答案
当你必须用动态内存分配的方式
去申请内存单元的时候
那么动态分配的这些单元
没有机会给它起变量名
没有机会给它起个数组名
那这个时候怎么办
它返回就是一个首地址
在这种情况下
我们迫不得已就必须用地址
去访问存储空间了
所以呢
前面举的那些例子
都是让大家首先学会
指针的语法
做好铺垫 做好准备
接下来
就是我们必须使用指针的时候了
首先呢我们来看
动态申请类型的操作符new
动态申请内存
在C++中是一种运算
new是一个operator
一个运算符
那么它的语法呢
就是new
后面要给一个类型名
类型名T
接下来可以在括号里面
列出初始化列表
也就是动态分配内存空间
动态申请内存空间
它的目的是用来存放
T类型的数据
并且呢
给出了数据的初始值
如果你需要初始化的话
可以给出初始化列表
它的功能是在程序执行的期间
去申请内存空间
那么当然这种申请的结果
有可能成功
也有可能不成功
比如说你要申请的空间很大
但是目前你内存不够了
那这个时候
你动态申请内存空间这个操作
就可能不成功
当成功的时候
这个操作
它返回的就是T类型的指针
指向的是新分配的
内存的单元的起始地址
比如说你分配内存单元
用于存放一个int数据
可能就跟你分配了四个字节
那么成功呢
就是返回
这四个字节的首字节的地址
关于异常呢
我们会在第十二章
再详细给大家介绍
俗话说叫做有借有还 再借不难
对于内存也是这样
用new动态申请的内存
一旦不再使用了
应该用对应的delete操作
去释放它
delete后面写出
你要释放的地址就可以了
那么这个delete后面
列出的地址呢
必须是当初曾经用new操作
返回的地址
而不能是一个什么别的地址
现在我们通过一个例题
来看一下
如何动态的创建一个对象
现在我们来看
我们想动态创建
这个点类的对象
点类的定义
跟我们以前的例子中看到的
仍然是一样的
那接下来我们看在主函数中呢
定义指向点类的Point类的指针
ptr1
然后呢用new运算
在运行时
动态申请内存用于构造
一个点对象
这个点对象的需要内存空间
申请好了 构造好了
就将它的地址赋给
或者初始化给这个指针ptr1
接下来呢
大家可能觉得怎么刚
把内存分配好了
指针初始化了
怎么马上就删除呢
这中间可能在真正的应用程序中
会有比较长的一段时间
一直在使用这个ptr1
指向point做各种操作
当不需要的时候呢
就去删除它
这是一个简单的模拟
好 接下来呢
当释放了
这个动态分配的point对象以后呢
我们又再动态分配
另外一个point对象
这一次呢是给了参数的
刚才没有给参数
是按默认方式构造的
再动态分配内存空间
构造这样一个对象
再次将首地址赋给ptr1
当用过不用之后呢
可以再删除它
而且一定要记得delete删除它
那么这里呢
我们要注意到
删除
是删除这个指针所指向的对象
释放它的空间
绝对不是删除指针自己
你看这个指针变量它还在
一会它可以接收别的赋值
所以不是删除指针自己
指针是主函数的一个局部变量
当主函数运行结束的时候
当然这个指针自己的空间
也会被释放的
那我们来看这两个点分别的构造
和析构的过程
第一步呢
先构造一个点对象
没有给初始值
所以是调用的默认的构造函数
Default Constructor called
然后接下来
当删除它的时候
调用了析构函数
Destructor called
接下来
再一次构造点对象的时候
给了初始值了
是调用的有参数的构造函数
看到这儿
constructor called
然后再一次delete
释放ptr1所指向的对象的时候呢
又调用析构函数
Destructor called
-导学
--第1章导学
-计算机系统简介
--计算机系统简介
--计算机系统简介 测试题
-计算机语言和程序设计方法的发展
--计算机语言和程序设计方法的发展 测试题
-面向对象的基本概念
--面向对象的基本概念 测试题
-程序的开发过程
--程序的开发过程
--程序的开发过程 测试题
-信息的表示和储存
--计算机的数字系统
--数据的编码表示
--信息的表示和储存 测试题
-实验指导
-导学
--第二章导学
-C++语言概述
--C++语言概述 测试题
-基本数据类型、常量、变量
--程序举例
--基本数据类型、常量、变量 测试题
-运算与表达式
--运算与表达式 测试题
-实验二:简单程序设计(上)
-数据的输入和输出
--数据的输入和输出
--数据的输入和输出 测试题
-选择结构
--if语句
--switch语句
--选择结构 测试题
-循环结构
--for语句
--循环结构 测试题
-自定义类型
--自定义类型
--自定义类型
-第2章小结
--第二章小结
-实验二:C++简单程序设计(下)
-导学
--导学
-函数定义
--函数定义
--函数定义 测试题
-函数调用
--例3-2
--例3-3
--例3-4
--例3-5
--例3-6
--函数调用 测试题
-嵌套与递归
--例3-9
--例3-10
--嵌套与递归 测试题
-函数的参数传递
--函数的参数传递
--函数的参数传递 测试题
-引用类型
--引用类型 测试题
-含有可变参数的函数
--含有可变参数的函数 测试题
-内联函数
--内联函数 测试题
-constexpr函数
--CONSTEXPR函数课后习题
-带默认参数值的函数
--带默认参数值的函数 测试题
-函数重载
--函数重载 测试题
-C++系统函数
--C++系统函数习题
-第3章小结
--第三章小结
-实验三(上)函数的应用
-实验三(下)函数的应用
-导学
--导学
-面向对象程序的基本特点
--面向对象程序的基本特点 测试题
-类和对象
--类和对象的定义
--类和对象 测试题
-构造函数
--构造函数基本概念
--委托构造函数
--复制构造函数
--构造函数 测试题
-析构函数
--析构函数
--析构函数 测试题
-类的组合
--类的组合
--类的组合程序举例
--前向引用声明
--类的组合 测试题
-UML简介
--UML简介
--UML简介课后习题
-结构体与联合体
--结构体与联合体 测试题
-枚举类
--枚举类
--枚举类 测试题
-第4章小结
--第四章小结
-实验四(上)
--实验四(上)
-实验四(下)
--实验四(下)
-导学
--导学
-标识符的作用域与可见性
--标识符的作用域与可见性 测试题
-对象的生存期
--对象的生存期
--对象的生存期 测试题
-类的静态成员
--类的静态成员 测试题
-类的友元
--类的友元 测试题
-共享数据的保护
--共享数据的保护 测试题
-多文件结构和预编译命令
--多文件结构和预编译命令 测试题
-第5章小结
--小结
-实验五
--实验五
-导学
--导学
-数组的定义与初始化
--数组的定义与使用
--一维数组应用举例
--数组的定义与初始化 测试题
-数组作为函数的参数
--数组作为函数的参数 测试题
-对象数组
--对象数组
--对象数组 测试题
-基于范围的for循环
-指针的定义和运算
--指针的定义和运算 测试题
-综合实例
--综合实例
-实验六(上)
--实验六上
-指针与数组
--指针数组
--指针与数组 测试题
-指针与函数
--指针类型的函数
--指向函数的指针
--指针与函数 测试题
-对象指针
--对象指针
--对象指针 测试题
-动态内存分配
--动态内存分配 测试题
-智能指针
--智能指针
-vector对象
--vector对象
--vector对象 测试题
-对象复制与移动
--移动构造
--对象复制与移动 测试题
-字符串
--C风格字符串
--string类
--字符串 测试题
-第6章小结
--第六章小结
-综合实例
--综合实例
-实验六(下)
--实验六(下)