0
点赞
收藏
分享

微信扫一扫

C++回顾与程序性能分析

金穗_ec4b 2022-02-11 阅读 51

文章目录

C++回顾

函数与参数

模板函数

template<class T>
T abc(T a, T b, T c)
	return a + b + c;

函数的签名:形参类型及形参个数所确定,如(int,int)。

异常

try{code}
catch(...){code}

try中的代码块抛出异常,进入第一个能捕捉到这种异常类型的catch块,同时其余的catch块被忽略。

动态存储空间分配

操作符new

new的值是一个指针,指向所分配的空间。

// 分配一个整数空间
// 定义y
int* y;
// 动态存储分配
y = new int;
// 为*y赋值
*y = 10;

具体内容可查看动态内存分配。

需要说明的有:

  1. 存储空间分配分为动态分配和静态分配(定义指针、数组、变量);
  2. 销毁空间时,指针会变成“”迷途指针“”,务必将其变成零值指针。

另外,我们在使用数组时,并不知道需要其多大,于是,常常会采用为数组分配动态内存的情况。

char* y = new float[n];

操作符delete

动态分配的存储空间不再需要时应该把它释放。

delete *y;
delete []x;

程序性能分析

程序性能指的是运行这个程序需要的内存和时间的多少。可以通过分析方法或实验方法来确定。

空间复杂度

空间复杂度的组成

程序所需要的空间主要由以下部分组成:

  1. 指令空间:指令空间是指编译之后的程序指令所需要的存储空间;
  2. 数据空间:所有常量和变量值所需要的存储空间,又分为静态和动态;
  3. 环境栈空间:环境栈用来保存暂停的函数和方法在恢复运行时所需要的信息,比如函数foo调用了函数goo,需要保存goo结束时函数foo继续执行的指令地址。

指令空间

  1. 把程序转换成机器代码的编译器;
  2. 在编译时的编译器选项;
  3. 目标计算机。

说明:
编译器的优化选项会减少指令的生成(比如对表达式的化简),而覆盖选项可以减少程序空间(多模块共用);

数据空间

在这里插入图片描述

环境栈空间

每当一个函数被调用时,返回地址和正在调用的函数的所有局部变量的值以及形式参数的值(该项仅对递归函数而言)会被保存在环境栈中。

分析空间复杂度

程序处理的问题实例都有一些特征,这些特征都包含着可以决定程序空间大小的因素(输入和输出的数量或相关数的大小)。

指令空间的大小受实例特征的影响不大。常量和简单变量所需要的空间与实例特征也没多大关系。

一些动态分配空间也可以不依赖实例特征。环境栈的大小一般也不依赖实例特征,除非用了递归函数。

可以把一个程序所需要的空间分为两部分:

  1. 固定部分。独立于实例特征。这一部分通常包括指令空间(即代码空间)、简单变量空间和常量空间等;
  2. 可变部分。由动态分配空间构成和递归栈空间构成。

于是有公式: c + S P ( 实 例 特 征 ) c+S_P(实例特征) c+SP()

int factorial(int n){
	if(n <= 1) return 1;
	else return n* factorial(n-1);
}

首先32位机器的返回地址大小为4字节,形式参数n的大小为4字节,同时,其递归深度为 m a x { n , 1 } max\{n,1\} max{n,1}。所以, S f a c t o r i a l ( n ) = 8 ∗ m a x { n , 1 } S_{factorial}(n)=8*max\{n,1\} Sfactorial(n)=8max{n,1}

所谓实例特征就是影响空间、时间复杂度的特征。

时间复杂度

影响空间复杂度的因素也影响时间复杂度。

一个程序P所需要的时间是编译时间和运行时间之和。编译时间与实例特征无关。一个编译过得程序可以运行若干次而不需要重新编译。

我们所关注的程序的允许时间通常用 t p ( 实 例 特 征 ) t_p(实例特征) tp()来表示。

t p ( n ) = c a A D D ( n ) + c s S U B ( n ) + . . . t_p(n)=c_aADD(n)+c_sSUB(n)+... tp(n)=caADD(n)+csSUB(n)+...
其中c是对应操作需要的时间,ADD、SUB是程序执行该函数的次数。

上述时间复杂度和空间复杂度的公式的表示都是尽可能贴近真实的(单位为秒、字节)。

下面介绍两种比较容易控制的,估算运行时间的分析方法。

操作计数

估算一个程序或函数的时间复杂度,一种方法是选择一种或多种关键操作,然后确定每一种操作的执行次数。使用这种方法成功与否取决于是否能够找到耗时最大的操作

操作计数是基于特征实例的函数。

因为平均操作计数不易确定,所以通常是分析最好和最坏两种操作计数。

步数

操作计数是针对选定操作而忽视其他操作的。

步数也是实例特征的函数。将对程序/函数的所有操作部分都进行统计。

任何一个实例都有若干个特征(输入个数、输出个数、输入和输出的大小),但是步数是特征的一个子集的函数。

要确定一个程序的步数,首先要确定所采用的实例特征。接着再确定什么是一步。

一个程序步可以定义为一个语法或语义上的程序片段,该片段的执行时间独立于实例特征

举报

相关推荐

0 条评论