C++四個基本準則及其具體體現

2020-10-11 01:00:16

C++程式語言的四個基本準則分別為無二義性(最高準則)、高效性(次高準則)、合乎日常習慣(第三準則)、相似相同原則(補充準則)。關於次四個基本準則的具體體現詳細討論如下:

一、最高準則:無二義性

這條準則不僅僅是C++的準則,更是所有程式語言的準則。無二義性指的是C++語言在程式設計時,不存在兩種不同的執行方式,每條語句對計算機而言只有一種執行操作。計算機的計算理解方式不同人腦,人腦會對接收的資訊進行篩選處理而儘可能消除歧義,而計算機在執行有兩種或多種意義的程式語言時因無法選擇而出現錯誤。

1. 無二義性準則的具體體現

  •  運運算元的優先度與結合性

(1) 運運算元的優先度大致與算數運運算元的優先度相同,即「先乘方,再乘除,後加減,有括號先算括號裡面的」。如下圖所示的程式碼塊,計算結果將會是33,而不是48或是其他。

int a = 3+5*6
cout << a << endl;

另一個典例就是字尾運運算元的優先順序比一元運運算元*高,這意味著加號運運算元將對str進行操作,而不會對*str進行操作。也就是說,將指標加1,結果是使其指向下一個字元,而不是修改被指標指向的字元。

char *str = "Hello World";
char ch = *str++;

在上例中,由於++是字尾形式,因此將在將*str的值賦給ch後,再將指標加1。因此上述程式碼將字元H賦給ch。然後移動指標str,使之指向字元e。 

(2)運運算元的結合性是指同一優先順序的運運算元在表示式中的操作方向。例如 1-2+3 的運算順序是先減後加,而不是先加後減;又如x=y=z 的賦值順序是先將z的值賦給y,再將y的值賦給x。

  •  識別符號不能以數位開頭

這是最高準則——無二義性的體現。若識別符號以數位開頭,那麼計算機將無法判斷其為一個數位還是一個常數,這樣的話就會出現二義性。

  •         貪心規則

這同樣也是最高準則——無二義性的體現。 貪心規則即指在對問題求解時,總是做出在當前看來是最好的選擇。即當有多種可行解決路徑時,計算機總會尋找最短路徑,這在一定程度上也是最高準則「無二義性」的體現。較為典型的是《演演算法導論》中的「活動選擇問題」與「區間排程問題」。

二、次高準則:高效性 

 1.陣列下標0索引

 陣列是一段連續的空間。下標的含義為當前元素到第一個元素的偏移量。那麼第一個元素的下標自然就是0,第二個元素的下標為1,依次類推第n個元素的下標為n-1。陣列是儲存在一片連續的記憶體空間中,編譯器可以直接通過第一個元素的地址(即陣列地址)和相應元素的下標(即距首元素的偏移量)來得到其相應的地址。

如果陣列索引從0開始,則a[i]的地址=首地址+i*每個資料所佔長度;

如果陣列下標從1開始,那麼a[i]的地址=首地址+(i-1)*每個資料所佔長度。顯然計算機需要多進行一次減法操作(詳見參考文章)。這體現了其高效性。

 2.邏輯短路

 邏輯短路主要見於「或」、「與」、「非」的邏輯計算中。

// &&(與邏輯運運算元) 有0為0,全1為1
0 && 0 = 0
0 && 1 = 0
1 && 0 = 0
1 && 1 = 1
// || (或邏輯運運算元) 有1為1,全0為0
0 || 0 = 0
0 || 1 = 1
1 || 0 = 1
1 || 1 = 1
// !  (非邏輯運運算元) 反轉,1變為0,0變為1
!0 = 1
!1 = 0
# 互斥或   相同為0,不同為1
# 同或   相同為1,不同為0

&&(和邏輯運運算元)運算,當前面為0時,後面部分不進行計算,發生短路;||(或邏輯運運算元)運算,當前面為1時,後面部分不進行計算,發生短路。這樣保證了程式計算的高效性。 

三、第三準則:合乎日常習慣

對於一種程式語言,設計的目的之一應該是方便人們使用。參考程式語言Python,Tim Peter撰寫的「Python之禪」中就闡明瞭程式語言應該方便人們使用,儘可能便捷。

同樣在編寫程式時C++的語法規範要適合程式設計師使用,為其帶來便利。下面列舉幾個典型範例。 

(1)運算順序 

在運算C++程式時,對於同級運運算元,其運算順序是由左至右的(這與數學運算習慣一致)。程式執行順序也是從上到下、由左至右的(這與人們日常閱讀習慣一致的) 

 (2)陣列下標索引

對於二維陣列a[1][2],其表示索引陣列a的第一行第二列,符合人們日常使用及閱讀習慣。

(3)變數的命名以及註釋 

在變數第一個字元必須是字母或下劃線,以及關鍵字限制外,變數命名的自由度使得程式設計師可以通過變數的實際意義來命名,以達到既成功建立一個變數,又能清晰地明白變數的意義。例如在設計學生成績管理系統時可以使用student_score來儲存/接收使用者輸入的「學生成績資訊」;使用「Chinese」來儲存/接收使用者輸入的某學生的語文成績。 

此外,在團隊合作編寫大型專案程式碼或隔段時間重新編寫以往程式碼時,註釋的功能使得程式設計師之間的共同作業效率及程式設計師直接的閱讀程式碼效率得到提高。且C++註釋格式較為簡單,常用的註釋格式為//與/*。 

四、補充準則:相似相同準則 

 在C++語言中,如果有兩個不同的物件具有相似的行為,那麼C++會為這兩個物件額外增加對方的行為,使得這兩個不同物件具有對方的相同行為。通俗來說,就是若有兩個不同的物件A與B,且其分別有行為a與b。當行為a與b相似時,C++則自動為A增加行為b,為B增加行為a,即A、B共同擁有行為a、b。這有利於程式的簡化。下面介紹一些該準則的具體體現。

(1) 初始化

 C++有三種初始化方式,即等號初始化、括號初始化與列表初始化。

// 等號初始化
int a = 5;
int k = a;
// 括號初始化 
int k(5);
int k(i);
// 列表初始化
int j{i};
int j{5}'
int j={i};
int j={5};

括號初始化是變數與物件之間的「相似相同規則」;列表初始化是變數與陣列之間的「相似相同規則」。本質上是C++將變數、物件及陣列統一對待的原則的產物。

  • 變數初始化 

定義變數a=1時,一般為int a = 1;但也存在 int a(1);的情況(括號的初始化,形似物件的初始化),此外還有 int a ={1} (形似陣列的初始化)以及 int a = ({1})這樣的初始化形式。

// 一般形式的初始化格式
int a = 1;
// 括號的初始化,形似物件的初始化
int a(1);
//形似陣列的初始化
int a{1};
//其他初始化格式
int a=({1});
  •  陣列初始化

 對於陣列a[5],其初始化一般為a[5] = {};(中括號內不填,則預設初始為0;也可以依次填入資料進行初始化)。在C++11標準中,初始化可以直接a[5]{};(陣列與變數的相似相同)。

  • 參照初始化

所謂參照,相當於給變數起個別名。如int a=5;int &b=a;,值得注意的是,參照必須在定義時進行初始化。對於參照的初始化,除了有int &b=a;也有int &b(a);(參照與變數的相似相同規則) 。

  • 指標初始化

指標本身就是變數。因此,變數具有的行為,指標同樣都會有且只會多不會少。變數有八種初始化形式,因此,指標必然也會有八種初始化形式。 

 (2)陣列與指標賦值

 以對下標為5的陣列賦值為例:

int a[10], *p = a;

通過指標存取,應該寫為:

*(p + 5) = 3;

通過陣列存取,應該寫為:

a[5] = 3; 

根據相似相容原則,此時應有如下四種寫法,即指標學會了陣列的寫法,陣列學會了指標的寫法。

*(p + 5) = 3;
a[5] = 3;
*(a + 5) = 3;
p[5] = 3;

以上即為上課所學知識,若有錯誤之處敬請斧正!為尊重參考文章的作者的知識成果,本文參考之處已設定超連結且連結至原文。