C++函數中const引用形參的一點理解

一、寫在前面    

    作爲一個初級而且想成爲高級的程序員,對浩瀚的代碼世界總是充滿的好奇與學習的動力,哈哈,別笑,我是認真的。最近之所以頻繁的更新博文,而且知識點相對比較廣,但大多也是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不必每次都重新讀取,直接使用第一次讀取的值(我想應該是存放在寄存器文件中的)。


四、寫在後面

    以下純屬個人理解,如有錯誤或不足的地方請批評指正。

    現在關於編寫高效優質的代碼有三種說法,一部分認爲需要以內存空間換時間,因爲現代計算機的內存速度、大小都有很大的進步,內存空間緊張已不再是問題;另一部分認爲需要以時間換空間,因爲他們任務現代計算機的計算單元的計算速度已經很快了,不需要考慮計算效率的問題;還有一部分人(那就是我,哈哈),綜合前兩種情況,在適當情況下,當然可以兩種互換啦。




發佈了40 篇原創文章 · 獲贊 127 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章