动态存储分配
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
16
Point::Point() { x = rand() % 101; y = rand() % 101; }
17
int main() { Point *ptr[5] = {NULL}; srand(time(NULL));
int i = 0; for( ;cin.get() == '\n' && i < 5; i++) { ptr[i] = new Point; ptr[i]->print(); }
基本类型一般不采用动态存储分配
12
2018/10/11
动态存储空间的回收
用new分配的空间一定要用delete回收 具体使用格式: delete 指针变量名
delete[] 指针变量名 //用于动态数组的内存回收 delete只能用于回收new所分配的空间 对于一个指针指向的堆对象只能执行一次 delete操作 delete[]忽略括符内的具体数字,无论是几维数 组的空间回收均只用一个括符表示
2018/10/11
23
#include "vector.h" int main() { int arr[5] = {1,2,3,4,5}; vector v1(arr,5),v2;
cout << "elems at index " << 3 << " : " << v1.at(3) << endl; cout << "length of v2 is : " << v2.len() << endl;
Vector有别于C语言中的静态数组,它有体现数组大小 的成员size 思考:Vector具有哪些成员?如何在程序运行起来以 后,根据用户从键盘输入的n和m创建数组?
2018/10/11
20
分析
Vector 的数据成员有: int SIZE;//数组当前元素个数 int elems[n];??? 还是int *elems;??? Vector 的成员函数有: 构造函数(3个,分别实现默认初始化和带参初始化) 返回下标为i的元素,int at(int index); 输出数组所有元素,void print(); 返回数组当前元素个数,int size(); 动态创建数组需要用到动态存储分配 静态数组指数组长度在编译时即定义好,在整个程
Point类
void print() const; int getX() const; int getY() const; private: int x; int y; };
2018/10/11
15
//内联函数的声明应出现在函数定义体上 inline int Point::getX() const { return x; } inline int Point::getY() const { return y; } void Point::print() const { cout << '(' << x << ',' << y << ')' << endl; }
}
2018/10/11
22
构造函数的初始化列表
vector::vector(int ilen,int *ielems) :length(ilen) { int i;
elems = new int[length]; for(i = 0 ; i < length; i++) elems[i] = ielems[i]; }//初始化列表只能出现在成员函数的定义中!!
return 0; }
2018/10/11
24
vector的析构函数
vector::~vector() { cout<<"对象正在析构…… " <<endl; delete [] elems;//回收指针elems所指堆内存 }
2018/10/11
25
几点说明
析构函数与类同名,无参数,无需指定返回值
析构函数不能有参数,因此不能重载
析构函数不能回收对象本身所占空间 如果不需要做清理工作,类可以没有析构函数 思考: 在vector中,对象v1和v2能不能正确析构?? 考虑对象的内存分布……
2018/10/11
26
对象的复制机制
v1 5 3050 1 2 3 4 5 堆对象 hello
2018/10/11
2018/10/11
13
说明以下定义的区别
a) int ival = 1024; b) int *pi = &ival; c) int *ip2 = new int(1024); d) int *ip3 = new int[1024];
2018/10/11
14
class Point { public: Point(); //难点
5
对象的清理工作
对象的清理工作由析构函数完成 主要功能: 在对象生存周期即将结束的时刻,由编译系统自
动调用来完成一些清理工作 在程序块执行完最后一条语句后,系统自动调用 析构函数
语法格式为: <类名> :: ~<类名>() { <函数体> }
6
计算屏幕上若干点构成的折线长度
栈
堆 静态存储区
程序区
2018/10/11
9
程序中变量的内存分配方式
程序运行时需要占用多大的空间需要在编译时确 定,便于操作系统为程序分配适当的内存空间。 从静态存储区分配:程序的全局变量和静态变量 都在这里分配,且在编译时已经分配好,在程序 终止前被操作系统回收。 在栈上创建:在函数调用时,函数的形参和局部 变量都在栈上创建,函数执行完毕时这些内存自 动被释放掉。 从堆(heap)上分配:在程序运行期间,用动态存 储分配函数申请和释放的内存
18
double aver = 0; int x,y; cout << "---------------------------\n"; for(i = 0;i < 4; i++) { x = ptr[i] -> getX() - ptr[i + 1] -> getX(); y = ptr[i] -> getY() - ptr[i + 1] -> getY(); aver += sqrt(x * x + y * y); } cout << "折线总长度是:" << aver << endl; for(i = 0 ;i < 5; i++) { delete [] ptr[i]; } system("pause"); return 0;}
19
练习--设计一个整型的Vector类
设计一个动态的整型数组类Vector,它能根据用户提供 的参数动态生成元素,即
Vector v1;//生成包含0个元素的空数组 Vector v2(n); //生成包含n个元素的数组
Vector v2(n,m); //生成包含n个元素,每个元素值为m的数组
具体声明格式: <类名>::<类名> (const <类名>& <对象名>) 复制构造函数只有一个参数,是该类对象的引用 若用户没有显式定义复制构造函数,编译器会自 动生成一个默认的复制构造函数,其功能是把已 知对象的每个数据成员都复制到新定义的对象中
2018/10/11
29
vector类的复制构造函数
其主要功能是创建并初始化对象
如果用户不自己定义构造函数,则编译器会自 动生成一个默认的构造函数。
2018/10/11
3
构造函数
定义格式: <类名> :: <类名> (<参数表>) { <函数体> } 构造函数名与类名相同,且不指定函数返回值 一般情况下,应该构造函数定义为公有成员 编译系统自动生成的默认构造参数其形式为: <类名> :: <类名> ( ) { }
主要内容
动态存储分配(难点) 程序在内存中的分布 new和delete运算符 复制构造函数——浅复制和深复制 析构函数 类的静态成员 分为静态数据成员和静态成员函数 静态数据成员如何初始化?是通过构造函数吗? 静态成员函数的定义和调用规则 多文件结构
2018/10/11
重点、难点
10
2018/10/11
动态存储分配
由动态内存管理系统管理的这块内存区域叫做 “堆(heap)”: 当需要动态灵活地分配内存空间时,需要用到动
态存储分配
动态分配得到的内存块位于堆中,且没有名字
动态存储分配由库函数malloc.h提供 格式:p = (double* ) malloc(n*sizeof(double)) C++中动态存储分配由运算符new和delete实现 new和delete完成动态存储分配时,可以很好 地和构造函数、析构函数进行交互,malloc和 free不能自行调用构造函数和析构函数 2018/10/11 11
以下3种情况系统调用复制构造函数:
用类的一个对象初始化同类的另一个对
象时
对象作为函数参数传递给函数形参时 函数返回值是类的对象,函数调用完成
时返回
2018/10/11
用Point类描述位于第 一象限的点。用户敲 击一次ENTER键,程 序创建一个点,该点 的横纵、坐标值随机 ,并在[0,100]。敲击5 次以后,计算所有点 构成的折线总长度。
7
分析
思路
定义Point类,思考该类具有哪些成员
定义5个Point类的对象,调用成员函数分别获取每
个点的横、纵坐标值
动态存储空间的分配
具体方法: 指针变量名 = new 类型;
指针变量名 = new 类型 (初值);
指针变量名 = new 类型 [元素个数]; 当执行new时,有两件事发生: 大小适当的空间被分配给特定类型的变量; 该存储空间首地址作为new表达式的返回值,若分
配失败则返回0 ;
vector::vector(const vector & v) { length = v.length; elems = new int[v.length]; for(i = 0 ; i < length; i++) elems[i] = v.GetElemsi[i]; }
2018/10/11
30
理解复制构造函数的作用及其调用时机,能正 确完成含有资源的对象复制 理解析构函数的作用和调用时机,能正确利用 析构函数完成对象相关资源的清理
能正确使用静态成员解决实际问题
2018/10/11
回顾--对象的初始化
对象在定义的时候对其数据成员进行初始化, 称为对象的初始化 C++中对象的初始化由一个特殊的成员函数 (构造函数)完成
2018/10/11
4
复制构造函数
主要功能 :
用一个已知的对象来初始化一个同类对象
具体声明格式: <类名>::<类名> (const <类名>& <对象名>) 复制构造函数只有一个参数,是该类对象的引用 若用户没有显式定义复制构造函数,编译器会自 动生成一个默认的复制构造函数,其功能是把已 知对象的每个数据成员都复制到新定义的对象中
v2 5
3050
Copy
3Fra Baidu bibliotek50
s 5
Copy
?
27
深复制、浅复制
s 堆对象 s 堆对象
浅 复 制
5
hello
Copy t 5
深 复 制
5
hello
Copy t 堆对象 hello 5
2018/10/11
当对象拥有资源时,C++提供复制构造函数实现深复制
28
复制构造函数
主要功能 :
用一个已知的对象来初始化一个同类对象
通过循环计算5点构成的折线长度
难点
如何为每个点生成满足题目范围的随机坐标值
如何实现用户敲击一次键盘,创建一个点?
2018/10/11
是否是:Point pt[5];?????????
8
程序的内存映象
试着思考:为什么定义数组的时候 下标必须是常量? int arr[10]; 为什么不能是:int m,int arr[m]; scanf(“%d”,&m); 一个已经编译完成的C程序取得并 使用4块在逻辑上不同并且用于不 同目的的内存区域。
21
序运行过程中,大小无法改变 动态数组在程序运行中,可根据需要重新指定大小 2018/10/11
vector::vector(int ilen,int *ielems) { int i;
length = ilen; elems = new int[length]; for(i = 0 ; i < length; i++) elems[i] = ielems[i];