C++函数中const引用形参的一点理解

来源:互联网 发布:网络信息有限公司名字 编辑:程序博客网 时间:2024/05/21 17:41

一、写在前面    

    作为一个初级而且想成为高级的程序员,对浩瀚的代码世界总是充满的好奇与学习的动力,哈哈,别笑,我是认真的。最近之所以频繁的更新博文,而且知识点相对比较广,但大多也是C++各方面的基础,再加上最近时不时度一些别人在微信公众号上推送的技术文章(如果你也想了解这些技术公众号,也可以关注我,我反正觉得蛮好的,查看这位博友的博文吧程序猿关注的微信公众号和网站),就产生了一些技术联想,恰好又在写代码的过程中用到了或遇到了,索性就把这些都记录下来吧。


二、CPU指令执行局部性原理

    一个编写良好的计算机程序代码常常具有良好的局部性,也就是说它们倾向于引用最近引用过的数据项本身,或者引用与最近引用过的数据项在内存空间(关于内存空间的解释请看一幅图理解计算机系统硬件组成)中相隔比较近的数据项,这种倾向性称为局部性原理。局部性原理包含两个方面的内容:时间局部性空间局部性。所谓时间局部性指的是当前被引用的这个变量很可能在不久的将来(即几个机器指令周期之后)在此被引用;而空间局部性指的是CPU很可能在不久的将来引用与当前所引用变量内存空间中相邻的变量。这里举例两个时间局部性和空间局部性的例子,关于时间局部性,比如一个函数定义如下:

void fun(int n){    //数组a[100]是一个全局数组    for(int i=0; i<100; i++)    {        a[i] = a[i] + n;    }}
如果调用函数fun(10),则在for循环内CPU每次都需要重新读取n的值(尽管现在一些编译器会做一定的优化),这就不是一个时间局部性良好的代码,可以修改为如下:

void fun(int n){    int a = n;    //定义局部变量,接管实参n的值,避免CPU每次都重新读取n的值,保证时间局部性    //数组a[100]是一个全局数组    for(int i=0; i<100; i++)    {        a[i] = a[i] + n;    }}


对于空间局部性,以访问二维数组为例:
void fun_1(int *a[M], int N){    //N为二维数组行数,M为二维数组列数    for(int i=0; i<N; i++)    {        for(int j=0; j<M; j++)        {            a[i][j] = a[i][j] + 1;        }    }}

void fun_2(int *a[M], int N){    //N为二维数组行数,M为二维数组列数    for(int i=0; i<M; i++)    {        for(int j=0; j<N; j++)        {            a[i][j] = a[i][j] + 1;        }    }}
比较函数fun_1()和fun_2(),可以发现,他们的函数体基本相同,都是包含两个for循环,也就是遍历二维数组的各个元素,但是函数fun_1()比fun_2()的空间局部性要好,为什么呢?因为二维数组在计算机内部是按行存储的。


三、C++中尽量使用const引用形参

    为什么呢?我的理解这也是为了保证时间局部性,在上面的例子中,我提到通过定义局部变量,即拷贝实参来保证时间局部性,但是当实参是一个很大的数组(数组无法拷贝)、或者是一个没有定义拷贝构造函数(关于C++拷贝构造函数可以链接深入理解C++对象模型之拷贝构造函数)的对象(这时编译器需要决定是否要合成拷贝构造函数,然后再执行相应的拷贝操作),但是拷贝的过程需要更长的时间消耗,本来定义一个局部变量是一种以内存空间换时间的概念,但是现在局部变量的拷贝时间太长,导致内存空间被消耗,同时并没有换取时间的减少,所以是得不偿失的,那怎么办呢?C++提供了const关键字,const关键字的作用很多,这里只解释它作为函数形参的一个作用,主要有两个作用:(1)它告诉编译器,这个参数是一个常量,首先你在函数内部不能改变它;(2)其次,如果在函数内部需要多次引用这个值,CPU不必每次都重新读取,直接使用第一次读取的值(我想应该是存放在寄存器文件中的)。


四、写在后面

    以下纯属个人理解,如有错误或不足的地方请批评指正。

    现在关于编写高效优质的代码有三种说法,一部分认为需要以内存空间换时间,因为现代计算机的内存速度、大小都有很大的进步,内存空间紧张已不再是问题;另一部分认为需要以时间换空间,因为他们任务现代计算机的计算单元的计算速度已经很快了,不需要考虑计算效率的问题;还有一部分人(那就是我,哈哈),综合前两种情况,在适当情况下,当然可以两种互换啦。




0 0
原创粉丝点击