Category: CPP

C++ conception and more applications.

  • C++ 來搞懂函數的傳值Call by value、傳址Call by pointer以及傳參考Call by reference。

    學生時代…
    作者在學這一章節時, 坦白講….腦袋一片空白, 幾乎是用死背阿!

    當出了社會後幾年(本行是玩PLC、Software platform、數位原理以及通訊拆解), 之後再來看CPP 這一章節, 變得很好從底層出發, 去了解這個語言獨有的一些 記憶體操作方法。

    在C++ 世界裡面, 我們常常會利用函數去做運算, 甚至是處理些重複性高的工作

    在講解函數之前,必須先把何謂函數的引數和參數弄個清楚。

    函數引數(argument)以及參數(parameter)

    以下介紹參考來源

    函數的引數(argument) v.s. 函數的參數(parameter)
    使用函數(或稱函式或副程式)時,常常會遇到這兩個名詞,本人也時常混淆,每個編輯的翻譯也不盡相同,但由於非常重要,必須做好釐清。

    1. 參數(parameter)用於「函數的宣告」,也就是在定義函數,或者宣告函數的原型時使用。由於必須要在函數的小括號內寫上參數的型態,故又稱為「形式參數」,可記為「參數的型式」。
      A. 在定義函數時:
      void swapfunction(int x, int y) // x , y稱為參數(parameter),小括號內要寫上參數的型態
      { 函數定義域的程式碼,以參數x、y來撰寫敘述 ………
      }
    2. 引數(argument)是用於「呼叫函式」,也就是「執行函數」時的「輸入值」。
      B. 呼叫(執行)函數時:
      swapfunction(a,b); // ()中的a , b稱為引數(argument),不需要寫上型態

    透過呼叫的方式來執行函數

    我們是在B.中設定兩個引數a、b來使用這個函數。當電腦看到引數a、b後,便會將a、b傳遞給A.內的參數x、y,以執行函數所定義的運算,所以傳遞的方向是:「由引數(a、b)傳遞給參數(x、y)」。


    傳值 Call by value

    如果你要簡單暴力的傳遞值的方式。

    • 把變數資料移動到記憶體裡面
    //函數定義
    int MathFun(int x, int y) {
        return x + y;
    }

    傳址 Call by pointer

    Call by pointer 在我看到的網站以及資料…. 很多人稱作 Call by addres,我比較喜歡用 Call by pointer 這名子,
    這邊以最簡單的swapfun作為範例
    其中在傳址時相當於 int *x = &a; int *y = &b; 這樣的寫法。

    檢測記憶體位置_會交換??

    
    
    int a = 6;
    int b = 10;
    
    // 觀察記憶體位置會不會變化?? 
    
    void swapfun(int* x, int* y) {
    
    	cout << x << endl;
    
    	cout << y << endl;
    
    	int tmp = *x;
    	*x = *y;
    	*y = tmp;
    
    	cout << x <<endl;
    
    	cout << y << endl;
    }
    
    int main(void) {
    	
    // 傳址* 型態 只會接受參考& 
    
    	swapfun(&a, &b);
    
    }
    
    
    不會!

    a、b、x、y 記憶體位址都不一樣!!!!

    *註釋:

    參數與引數 https://notfalse.net/6/arg-vs-param

    • void swapfun (參數)
    • swapfun (引數)
    • & (參考)

    傳址:

    *x = &y 經過這個address 等式指派給另一個地址, 這個傳址才算是完成!

    變數會交換??

    
    // 檢測 變數會不會交換??
    
    void swapfun(int* x, int* y) {
    	cout << *x << endl;
    
    	cout << *y << endl;
    
    	int tmp = *x;
    	*x = *y;
    	*y = tmp;
    
    	cout << *x <<endl;
    
    	cout << *y << endl;
    }
    
    int main(void) {
    
    	// 傳址* 型態 只會接受參考& 
    
    	swapfun(&a, &b);
    
    }
    
    
    它們交換了彼此!
    一旦接觸到記憶體交換的”用法” ,請在交換的陳述式裡面繼續使用這些方法

    傳參考Call by reference

    int a =0;

    int& Ref_variable =a;

    • 有趣的事情…. Ref_variable 沒有分配記憶體空間,而是Ref_variable 跟a共用了記憶體空間!
    • 這是很多語言都沒有的記憶體操作方法!

    參考連結

    
    int main(void) {
        // a 為字串變數
        string a = "There is pointer A.";
        cout << a << endl;
    
        // b 為對 a 的指標
        string* b = &a;
        cout << b << endl;
    
        // c 為對 a 的參考
        string& c = a;
        cout << c << endl;
    
        return 0;
    }
  • C++ Array

    陣列的宣告要包含三個資訊:

    • 每個元素儲存的資料類型
    • 陣列名稱
    • 陣列元素的數目

    以下是在C++ 簡單的宣告陳述

    // 型態  陣列名稱month [陣列個數]; 
    
    short month[12]; // 產生有12個 型態為short 的元素的陣列 

    建立一個抽象名稱months 的陣列, 且擁有12個元素, 每個元素儲存 short 型態的數值,

    宣告陣列語法

    型態  陣列名稱[陣列個數]; 

    陣列是複合型態

    由於C++ 用 “衍生” 表示 類別關係, 所以我們每次必須自己寫一個新的名詞!

    來源: The-C-20-Masterclass-Source-Code

    範例_01 宣告

    int main(){
    
        //Declare an array of ints
        int scores [10]; // Junk data
    
        //Read data
    
        std:: cout << " scores [0] : " << scores[0] << std::endl;
        std:: cout << " scores [1] : " << scores[1] << std::endl;
    
        return 0;
    
      }
    
    // scores [0] : -858993460
    // scores [1] : -858993460
        
    不清空初始化陣列,會有初始化資料在裡面。

    範例_02 陣列給予初始值

    int main(){
    
        //Declare an array of ints
        int scores[10]{0}; // Junk data
    
        //Read data
    
        std:: cout << " scores [0] : " << scores[0] << std::endl;
        std:: cout << " scores [1] : " << scores[1] << std::endl;
       
     return 0;
    }
    
    // scores [0] : 0
    // scores [1] : 0
    初始化數值可以只給一個, 全部的陣列都會給予初始值! 

    範例_03 每個陣列給予值

    int main(){
    
        //Declare an array of ints
        int scores[10]{1,1,1,1,1,1,1,1,1,1}; 
    
         //Read with a loop
        
        for( size_t i {0} ; i < 10 ; ++i){
            std::cout << "scores [" << i << "] : " << scores[i] << std::endl;
        }
        
     return 0;
    }
    scores [0] : 1
    scores [1] : 1
    scores [2] : 1
    scores [3] : 1
    scores [4] : 1
    scores [5] : 1
    scores [6] : 1
    scores [7] : 1
    scores [8] : 1
    scores [9] : 1
    此時你能一個個給予數值到每個陣列。

    範例_03 特定陣列初始化數值

    int main(){
    
    //Declare an array of ints
    int scores[10]{0}; // Junk data
    
    
       
        scores[0] = 20;
        scores[1] = 21;
        scores[2] = 22;
    
        ////Print the data out
        for( size_t i {0} ; i < 10 ; ++i){
            std::cout << "scores [" << i << "] : " << scores[i] << std::endl;
        }
    
        return 0;
    }
    scores [0] : 20
    scores [1] : 21
    scores [2] : 22
    scores [3] : 0
    scores [4] : 0
    scores [5] : 0
    scores [6] : 0
    scores [7] : 0
    scores [8] : 0
    scores [9] : 0
    其餘沒有給予值的陣列,都會給予 =0 的數值。
  • C++ Precedence And Associativity

    當你有算數的經驗時,你會知道在做四則運算時會有先乘除後加減的規則

    程式當然也有,C++ 裡面也有相關的先後順序與關聯性

    C++ Precedence and associativity

    先前觀念

    What is the purpose of {} in C++?

    {} can be used to initialise variables in C++11 in the same way that they are used to initialise arrays and structures in C.

    {} 可用於將C++ 已宣告的變數做 初始值代入。

    範例01

    #include <iostream>
    
    
    int main(){
    
    //初始值代入
        int a {6};
        int b {3};
        int c {8};
        int d {9};
        int e {3};
        int f {2};
        int g {5};
            
        int result = a + b * c -d/e -f + g; //  6 +  24  -   3 - 2 + 5
        
        std::cout << "result : " << result << std::endl;
    
        system("pause");
    
        return 0;
    }
    
    //結果:  6 +  24  -   3 - 2 + 5 = 30

    範例02

    #include <iostream>
    
    
    int main(){
    
        int a {6};
        int b {3};
        int c {8};
        int d {9};
        int e {3};
        int f {2};
        int g {5};
            
        int result = a + b * c -d/e -f + g; //  6 +  24  -   3 - 2 + 5
        
        std::cout << "result : " << result << std::endl;
    
        result = a/b*c +d - e + f;  //   16 + 9 - 3 + 2
        std::cout << "result : " << result << std::endl;
    
        system("pause");
    
        return 0;
    }
    
    //結果:  6 +  24  -   3 - 2 + 5 = 30
    //結果:   16 + 9 - 3 + 2 =24
  • C++ 基本架構

    學習C++ 已經是我大學時期的經驗了

    C++ 學習路徑會因為你所處的產業而有所不同並沒有快速且系統的學習路徑

    只有把基本觀念、架構以及開發環境設定弄熟,是學習者先需要有的認知。

    作者的學習路程

    • 剛開始碰觸是大學一年級 : 博碩文化出版的 C++ 物件導向 程式設定實例入門
    • 出社會後一年為了撿回語感再碰一次 C++
    • 2019~2022這段時間有空,研究一下一些開源的Lib以及機器學習
    • 最近參考書籍 C++ Primer Plus 5/e
    參考: http://www.w3big.com/zh-TW/cplusplus/cpp-intro.html#gsc.tab=0

    範例

    //匯入標準程式庫相關的輸出、輸入程式
    #include <iostream>
    
    //匯入標準程式庫相關的字串程式
    #include <string>
    
    //std 是標準程式庫的 命名空間
    using namespace std;
    
    //建立 建構子
    class Player
    {
        public:
    
    //建立 物件
            Player()
            {
    //cout 輸出字串內容
                cout << "Hello World!" << endl;
            }
    };
    
    //所有 C++ 程式都必須有函 main 式
    // () 內部沒有Return value 回傳值 = void
    
    int main()
    {
        Player mylayer;
        system("pause");
    }
    

    < 建構子內部的Public 封裝 解釋 >

    class Player
    {
        public:
             Player()
            {
                    cout << "Hello World!" << endl;
            }
    
    };
    
    因為C++ 預設類別為 Private
    建構子與類別具有相同的名稱,且沒有任何回傳值! 

    < 主程式 解釋 >

    int main()
    {
        // 類別 抽象名稱
        Player mylayer;
    
        // 讓 CONSOLE 暫停在此
        system("pause");
    }