運算子多載如何執行?int a = 10; ++a—;這串程式碼為什麼會出錯?居然跟左值右值有關!左值右值真的是一左一右嗎?參數傳遞中的傳指標和傳參考差在哪邊?C++居然無法回傳多值,那我該怎麼回傳多值?
還是很困惑嗎?文章裡有答案喔~😎
實務上,會建議介面和實作分離,一個粗糙的分法是.h檔為介面,.cpp檔為實作,但這樣的分法不完全正確。 介面是指使用者會使用到的東西,例如:public函數的標頭、class的標頭。而function的實作和private (member data)裡的東西,都不屬於是介面,因為使用者不會直接使用到這些東西。
因此通常#include進來的檔案是介面,檔案中不會看太多實作的細節。這樣有些好處:第一、使用者不用知道如何實作,只要學會如何使用介面,即可使用這些功能,所以套件也是介面與實作分開的例子。第二、如果套件的更新只更新實作部分,而不更動到介面部分,這樣使用者的程式碼不需要變動,也能更新套件的功能。而如果套件的介面與實作是合在一起的,每次套件更新,使用者就可能要再更新自己的程式碼,這樣的套件是不會有人想用的。
介面與實作分開並不會影響到編譯器 (complier)的運作,因為編譯器只需要知道函式名、回傳值、參數列,這也剛好是函式的標頭 (header)內容。只有linker or loader (OS的程式,loader也可以包含linker的工作)才需知道實作內容。
運算子 (operator)、函式 (procedure)、函數 (function),本質上無太大的差別,只不過運算子可以使用運算子符號來呼叫函式,當然也可以用函式形式來呼叫函式;而函式 (procedure)是指無回傳值 (void)的;函數 (function)則是指有回傳值的。不過函式與函數的區分並沒有太大的意義,因此也常會混用。
函式多載有些前提:(1)需要在同一個scope內,不同scope就不是overloading。(2) 函式名相同,但簽章 (signature)不同。因此對於C++來說,每個多載函式都是獨立的函式,他們都是不同的函式,因為各自有獨特的簽章。函式簽章通常包含:函式名、參數型態、參數排序。
然後也不是所有的程式語言都支援運算子多載,C++有支援,但JAVA不支援,所以在JAVA中必須用函式多載。運算子多載如何運作?以輸入為例:cout << int << double << string;
cout << int == cout.operator<<(int),這會回傳cout (ostream&),使得可以連續輸出。cout << 之所以可以輸入不同型態的變數,是因為<<為一個多載運算子。
Cout << int << double << string; == ( ( (Cout << int) << double) << string);
a<b<c必須拆成a<b && b<c,否則會有問題,因為這攸關結合性問題。a<b<c == ((a<b)<c),如果(a<b)為真,即會回傳1,因此((a<b)<c) == (1<c),顯然這不是我們要的結果。
&& 和 || 這兩個operator如果要overloading必須小心,e1 && e2 && e3 && e4……,原本如果e1為false,判斷就會結束,但如果overloading,此性質就會消失。
更多運算子優先順序的例子可以看期中考第8題
左值與右值明顯的議題會出現在賦值 (assignment)這一動作,如:a = 1、b = c。首先何謂左值?何謂右值?左值通常是等號左邊的那個變數,也就是a和b都是左值,變數的本質是有名有記憶體位置的,而左值必須為變數,因此左值一定是有名字的;右值通常是等號右邊的數,也就是1和c都是右值,1本身是一個樣板數字 (literal number),是一個暫時且沒有名字的東西,因此右值可以是沒有名字的東西。因此一個簡單的判斷左右值的方法即為,左值需有名,右值可無名。
有些運算子是涉及到賦值,如:=, ++, --, +=, -=, .......。++a == a = a + 1、—b == b = b - 1。以下有一個涉及到左右值的運算子問題:
int a = 10; ++a—; // == (++(a—))
請問上面的a值為何?9?10?11?錯誤?答案是Compiling error。 因為++a需要一個rvalue,因為++a內含一個assignment,但a--會給lvalue
然後++, —盡量不要和macro(文取代)一起使用,因為Macro是copy整串的指令,容易會有意外的side effect,而不是copy計算值,所以指令會在copy後才執行運算。
更多左值右值的例子可以看期中考第6題
C語言的參數傳遞都是call-by-value,而pointer可以call-by-address。C++的call-by-reference和C的call-by-address很像,只不過C中的& (get address) and * (dereference)在C++中,編譯器自動幫你做。
call-by-value的缺點就是效率不好,因為它是用複製的方式在傳參數,但優點就是原本的參數不會因為函數內對引數做任何改變,而有所影響。call-by-reference的效率就會比較好,因為它是傳參考,參考可以視為變數的別名,因此只要改變引數,就會改變原本的變數。有時為了追求效能,但要沒有改變資料,就可以使用const reference 。
© blink.com.tw