主頁 > 後端開發 > 《C++ Primer》筆記 第6章 函式

《C++ Primer》筆記 第6章 函式

2021-01-24 17:21:16 後端開發

  1. 任意兩個形參都不能同名,而且函式最外層作用域中的區域變數也不能使用與函式形參一樣的名字(形參就相當于該函式的區域變數),
  2. 形參名是可選的,但是由于我們無法使用未命名的形參,所以形參一般都應該有個名字,某類形參通常不命名以表示在函式體內不會使用它,不管怎樣,是否設定未命名的形參并不影響呼叫時提供的實引數量,即使某個形參不被函式使用,也必須為它提供一個實參,
  3. 在C++語言中,名字有作用域,物件有生命周期,
    • 名字的作用域是程式文本的一部分,名字在其中可見,
    • 物件的生命周期是程式執行程序中該物件存在的一段時間,
  4. 一個陳述句塊構成一個新的作用域,
  5. 形參和函式體內部定義的變數統稱為區域變數,其僅在該函式的作用域內可見,同時區域變數還會隱藏在外層作用域中同名的其他所有宣告,
  6. 我們把只存在于執行期間的物件稱為自動物件,當塊的執行結束后,塊中創建的自動物件的值就變成未定義的了,
  7. 區域靜態物件在程式的執行路徑第一次經過物件定義陳述句時初始化,并且直到程式終止才被銷毀,在此期間即使物件所在的函式結束執行也不會對它有影響,
  8. 如果區域靜態變數沒有顯式的初始值,它將執行值初始化,內置型別的區域靜態變數初始化為0,
  9. 如果函式無需改變參考形參的值,最好將其宣告為常量參考,
  10. 和其他初始化程序一樣,當用實參初始化形參時會忽略掉頂層const(從呼叫的角度來看),換句話說,形參的頂層const被忽略掉了,當形參有頂層const時,傳給它常量物件或者非常量物件都是可以的,注意:
      void fcn (const int i) { /* fcn 能夠讀取i,但是不能向i寫值 */ }
      void fcn (int i) { /*...*/ } // 錯誤:重復定義了fcn (int)
      // 在C++語言中,允許我們定義若干具有相同名字的函式,不過前提是不同函式的形參串列應該有明顯的區別,因為頂層const被忽略掉了,所以在上面的代碼中傳入兩個fcn函式的引數可以完全一樣,因此第二個fcn是錯誤的,盡管形式上有差異,但實際上它的形參和第一個fcn的形參沒什么不同,
    
  11. 陣列形參:
      // 盡管形式不同,但這三個print函式是等價的
      // 每個函式都有一個const int*型別的形參
      void print (const int*);
      void print (const int[]);
      void print (const int[10]); // 這里的維度沒有用,
    
  12. 給陣列形參指定長度:
      // 1. 使用標記指定陣列長度:
      void print (const char *cp) // C風格字串以'\0'結尾
      {
            if (cp)
                  while (cp)
                        cout << *cp++;
      }
    
      // 2. 使用標準庫規范:
      void print (const int *beg, const int *end) // 傳遞指向陣列首元素和尾后元素的指標
      {
            // 輸出beg到end之間(不含end)的所有元素
            while (beg != end)
                  cout << *beg++ << endl; // 輸出當前元素并將指標向前移動一個位置
      }
    
      // 3. 顯式傳遞一個表示陣列大小的形參:
      void print (const int ia[], size_t size) // 專門定義一個表示陣列大小的形參
      {
            for (size_t i = 0; i != size; ++i)
            {
                  cout << ia[i] << endl;
            }
      }
    
  13. 當函式不需要對陣列元素執行寫操作的時候,陣列形參應該是指向const的指標,只有當函式確實要改變元素值的時候,才把形參定義成指向非常量的指標,
  14. 形參也可以是陣列的參考,
      // 正確:形參是陣列的參考,維度是型別的一部分
      void print (int (&arr)[10]) // 這里的維度是必須的 // &arr兩端的括號必不可少
      {
            for (auto elem : arr)
                  cout << elem << endl;
      }
    
  15. 多維陣列的形參:
      // 兩者等價
      void print (int (*matrix)[10], int rowSize) { /*...*/ }
      void print (int matrix[][10], int rowSize) { /*...*/ }
    
  16. main:處理命令列選項 int main (int argc, char *argv[]) { ... },最后一個指標之后的元素值保證為0,
  17. 如果函式的實引數量未知但是全部實參的型別都相同,我們可以使用initializer_list型別的形參,initializer_list物件中的元素永遠是常量值,我們無法改變initializer_list物件中元素的值:
      void error_msg (ErrCode e, initializer_list<string> il)
      {
            cout << e.msg() << ": ";
            for (const auto &elem : il) // 因為initializer_list包含begin和end成員,所以我們可以使用范圍for回圈處理其中的元素,也可以寫成for (auto beg = il.begin(); beg != il.end(); ++beg)
                  cout << elem << " ";
            cout << endl;
      }
    
      if (expected != actual)
            error_msg (ErrCode(42), {"functionX", expected, actual}); // expected和actual是string物件
      else
            error_msg (ErrCode(0), {"functionX", "okay"});
    
操作 解釋
initializer_list lst; 默認初始化:T型別元素的空串列
initializer_list lst{a, b, c...}; lst的元素數量和初始值一樣多;lst的元素是對應初始值的副本;串列中的元素是const
lst2 (lst)或lst2 = lst 拷貝或賦值一個initializer_list物件不會拷貝串列的元素;拷貝后,原始串列和副本共享元素(畢竟是常量值)
lst.size() 串列中的元素數量
lst.begin() 回傳指向lst中首元素的指標
lst.end() 回傳指向lst中尾元素下一位置的指標
  1. 省略符形參(C語言特性,非C++):大多數型別別的物件在傳遞給省略符形參時都無法正確拷貝,void foo (parm_list, ...);void foo (...);第一種形式指定了foo函式的部分形參的型別,對應于這些形參的實參將會執行正常的型別檢查,省略符形參所對應的實參無需型別檢查,在第一種形式中,形參宣告后面的逗號是可選的,
  2. 一個回傳型別是void的函式也能使用return陳述句的第二種形式(return expression;),不過此時return陳述句的expression必須是另一個回傳void的函式,強行令void函式回傳其它型別的運算式將產生編譯錯誤,
  3. 在含有return陳述句的回圈后面應該也有一條return陳述句,如果沒有的話該程式就是錯誤的,控制流可能尚未回傳任何值就結束了函式的執行,很多編譯器都無法發現此類錯誤,
  4. const string &shorterString (const string &s1, const string &s2) { return s1.size() <= s2.size() ? s1 : s2; }其中形參和回傳型別都是const string的參考,不管是呼叫函式還是回傳結果都不會真正拷貝string物件,
  5. 不要回傳區域物件的參考或指標(回傳時區域變數可能已銷毀),要想確保回傳值安全,我們不妨提問:參考所引的是在函式之前已經存在的哪個的物件?
  6. 呼叫一個回傳參考的函式得到左值,其他回傳型別得到右值,可以像使用其它左值那樣來使用回傳參考的函式的呼叫,特別是,我們能為回傳型別是非常量參考的函式的結果賦值,
  7. 串列初始化回傳值:如果函式回傳的是內置型別,則花括號包圍的串列最多包含一個值,而且該值所占空間不應該大于目標型別的空間(所以int a = {3.14};是錯的),如果函式回傳的是型別別,由類本身定義初始值如何使用(可以看作用花括號內容初始化一個待回傳的臨時變數,該變數型別就是回傳值型別),
      vector<string> process()
      {
            // ...
            // expected和actual是string物件
            if (expected.empty())
                  return {}; // 回傳一個空vector物件
            else if (expected == actual)
                  return {"functionX", "okay"}; // 回傳串列初始化的vector物件
            else
                  return {"functionX", expected, actual};
      }
    
      // 猜猜func的回傳值會是什么?
      vector<string> func(void)
      {
            return {10, "hi"};
      }
    
  8. 如果控制到達了main函式的結尾處而且沒有return陳述句,編譯器將隱式地插入一潭訓傳0的return陳述句,
  9. 宣告一個回傳陣列指標的函式:
      // 1. C風格
      int (*func(int i))[10];
      // 2. 使用尾置回傳型別
      auto func(int i) -> int(*)[10]
      // 3. 使用decltype
      int odd[] = {1,3,5,7,9};
      int even[] = {0,2,4,6,8};
      decltype(odd) *arrPtr(int i) // decltype并不負責把陣列型別轉換成對應的指標,所以decltype的結果是個陣列
      {
            return (i % 2) ? &odd : &even; // 回傳一個指向陣列的指標
      }
    
  10. main函式不能多載
  11. 對于多載的函式來說,它們應該在形引數量或形參型別上有所不同(省略形參名字或僅僅改變變數名不算),不允許兩個函式除了回傳型別外其他所有的要素都相同,一個擁有頂層const的形參無法和另一個沒有頂層const的形參區分開來(底層const可以),
  12. 當我們傳遞一個非常量物件或者指向非常量物件的指標時,編譯器會優先選用非常量版本的函式,
  13. const_cast和多載:
      const string &shorterString(const string &s1, const string &s2)
      {
            return s1.size() <= s2.size() ? s1 : s2;
      }
      string &shorterString(string &s1, string &s2)
      {
            auto &r = shorterString(const_cast<const string&>(s1),const_cast<const string&>(s2));
            return const_cast<string&>(r);
      }
    
  14. 函式匹配是指一個程序,在這個程序中我們把函式呼叫與一組多載函式中的某一個關聯起來,函式匹配也叫做多載確定
  15. 當呼叫多載函式時有三種可能的結果:
    • 編譯器找到一個與實參最佳匹配的函式,并生成呼叫該函式的代碼,
    • 找不到任何一個函式與呼叫的實參匹配,此時編譯器發出無匹配的錯誤資訊,
    • 有多于一個函式可以匹配,但是每一個都不是明顯的最佳選擇,此時也將發生錯誤,稱為二義性呼叫
  16. 如果我們在內層作用域中宣告名字,它將隱藏外層作用域中宣告的同名物體(不論是函式名,還是變數名),在不同的作用域中無法多載函式名(內層函式會隱藏同名的外層函式),
  17. 在C++語言中,名字查找發生在型別檢查之前,
  18. 函式宣告放在同一個作用域中,則它將成為另一種多載形式,
  19. 默認實參:一旦某個形參被賦予了默認值,它后面的所有形參都必須有默認值,合理設定形參的順序,盡量讓不怎么使用默認值的形參出現在前面,而讓那些經常使用默認值的形參出現在后面,
      typedef string::size_type sz;
      string screen(sz ht = 24, sz wid = 80, char backgrnd = ' ');
    
  20. 如果我們想使用默認實參,只要在呼叫函式的時候省略該實參就可以了,函式呼叫時實參按其位置決議,默認實參負責填補函式呼叫缺少的尾部實參(靠右側位置),
  21. 多次宣告同一個函式也是合法的,在給定的作用域中一個形參只能被賦予一次默認實參,函式的后續宣告只能為之前那些沒有默認值的形參添加默認實參,而且該形參右側的所有形參必須都有默認值,
      typedef string::size_type sz;
      string screen(sz, sz, char = ' ');
      string screen(sz, sz, char = '*'); // 錯誤:重復宣告
      string screen(sz = 24, sz = 80, char); // 正確:添加默認實參 // 默認實參不在形參串列的結尾
      // 第一句和第三句如果調換順序則錯誤
      // 如果第三句再加上char = ' '就是重定義
      // VS2019報錯但可以運行
    
  22. 函式定義和函式宣告不能同時指定默認實參,通常,應該在函式宣告中指定默認實參,并將該宣告放在合適的頭檔案中,
  23. 區域變數不能作為默認實參,除此之外,只要運算式的型別能轉換成形參所需的型別,該運算式就能作為默認實參,
      // wd、def和ht的宣告必須出現在函式之外
      typedef string::size_type sz;
      sz wd = 80;
      char def = ' ';
      sz ht();
      string screen(sz = ht(), sz = wd, char = def);
      string window = screen(); // 呼叫screen(ht(), 80, ' ')
    
  24. 用作默認實參的名字在函式宣告所在的作用域內決議,而這些名字的求值程序發生在函式呼叫時,
      void f2()
      {
            def = '*'; // 改變默認實參的值
            sz wd = 100; // 隱藏了外層定義的wd,但是沒有改變默認值
            window = screen(); // 呼叫screen(ht(), 80, '*')
      }
    
  25. 行內說明(inline)只是向編譯器發出的一個請求,編譯器可以選擇忽略這個請求,一般來說,行內機制用于優化規模較小、流程直接、頻繁呼叫的函式,很多編譯器都不支持行內遞回函式,而且一個75行的函式也不大可能在呼叫點行內地展開,
  26. constexpr函式定義的幾項約定:函式的回傳型別及所有形參的型別都得是字面值型別;而且函式體中必須有且只有一條return陳述句,
      constexpr int new_sz() { return 42; }
      constexpr int foo = new_sz(); // 正確:foo是一個常量運算式
    
  27. 為了能在編譯程序中隨時展開,constexpr函式被隱式地指定為行內函式,
  28. constexpr函式體內也可以包含其他陳述句,只要這些陳述句在運行時不執行任何操作就行,例如,constexpr函式中可以有空陳述句、型別別名以及using宣告,我們允許constexpr函式的回傳值并非一個常量,當scale的實參是常量運算式時,它的回傳值也是常量運算式;反之則不然,(記住constexpr在編譯階段得出計算結果就行)constexpr函式不一定回傳常量運算式
      // 如果arg是常量運算式,則scale(arg)也是常量運算式
      constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
      
      int arr[scale(2)]; // 正確:scale(2)是常量運算式
      int i=2; // i不是常量運算式
      int a2[scale(i)]; // 錯誤:scale(i)不是常量運算式
    
  29. 行內函式和constexpr函式可以在程式中多次定義,但它的多個定義必須完全一致,基于這個原因,行內函式和constexpr函式通常定義在頭檔案中,
  30. assert是一種預處理宏assert(expr);,首先對expr求值,如果運算式為假(即0),assert輸出資訊并終止程式的執行,如果運算式為真(即非0),assert什么也不做,assert宏定義在cassert頭檔案中,
  31. 我們可以使用一個#define陳述句定義NDEBUG(一定要定義在#include <cassert>之前),從而關閉除錯狀態,(命令列:CC -D NDEBUG main.C相當于在main.C檔案的一開始寫#define NDEBUG
  32. 除錯幫助:
      #ifndef NDEBUG
            // __func__是編譯器定義的一個區域靜態變數,用于存放函式的名字
            cerr << __func__ << ": array size is " << size << endl;
      #endif
    
名稱 解釋
__func__ 輸出當前除錯的函式的名字
__FILE__ 存放檔案名的字串字面值
__LINE__ 存放當前行號的整型字面值
__TIME__ 存放檔案編譯時間的字串字面值
__DATE__ 存放檔案編譯日期的字串字面值
  1. 函式匹配的第一步是選定本次呼叫對應的多載函式集,集合中的函式稱為候選函式,候選函式具備兩個特征:一是與被呼叫的函式同名,二是其宣告在呼叫點可見,
  2. 第二步考察本次呼叫提供的實參,然后從候選函式中選出能被這組實參呼叫的函式,這些新選出的函式稱為可行函式,可行函式也有兩個特征:一是其形引數量與本次呼叫提供的實引數量相等,二是每個實參的型別與對應的形參型別相同,或者能轉換成形參的型別,(如果函式含有默認實參,則我們在呼叫該函式時傳入的實引數量可能少于它實際使用的實引數量,)
  3. 接下來,編譯器依次檢查每個實參以確定哪個函式是最佳匹配,如果有且只有一個函式滿足以下列條件,則匹配成功:
    • 該函式每個實參的匹配都不劣于其他可行函式需要的匹配,
    • 至少有一個實參的匹配優于其他可行函式提供的匹配,
  4. 呼叫多載函式時應盡量避免強制型別轉換,如果在實際應用中確實需要強制型別轉換,則說明我們設計的形參集合不合理,
  5. 實參型別轉換:
    • 精確匹配
      • 實參型別和形參型別相同
      • 實參從陣列型別或函式型別轉換成對應的指標型別
      • 向實參添加頂層const或者從實參中洗掉頂層const
    • 通過const轉換實作的匹配
    • 通過型別提升實作的匹配
    • 通過算術型別轉換或指標轉換實作的匹配
    • 通過型別別轉換實作的匹配,
  6. 分析函式呼叫前,我們應該知道小整型一般都會提升到int型別或更大的整數型別,有時候,即使實參是一個很小的整數值,也會直接將它提升成int型別,
      void ff(int);
      void ff(short);
      ff('a'); // char提升成int;呼叫ff(int);
    
  7. 所有算術型別轉換的級別都一樣,例如:從int向unsigned int的轉換并不比從int向double的轉換級別高,例如:
      void manip(long);
      void manip(float);
      manip(3.14); // 錯誤:二義性呼叫
      // 字面值3.14的型別是double,它既能轉換成long也能轉換成float,因為存在兩種可能的算術型別轉換,所以該呼叫具有二義性,
    
  8. 函式的型別由它的回傳型別形參型別共同決定,與函式名無關,
  9. 當我們把函式名作為一個值使用時,該函式自動地轉換成指標,此外,我們還能直接使用指向函式的指標呼叫該函式,無須提前解參考指標,注意,在指向不同函式型別的指標間不存在轉換規則,但是和往常一樣,我們可以為函式指標賦一個nullptr或者值為0的整型常量運算式,表示該指標沒有指向任何一個函式,
      // pf指向一個函式,該函式的引數是兩個const string的參考,回傳值是bool型別,
      bool (*pf)(const string &, const string &);
    
      pf = lengthCompare; // pf指向名為lengthCompare的函式
      pf = &lengthCompare; // 等價的賦值陳述句:取地址符是可選的
    
      bool b1 = pf("hello", "goodbye"); // 呼叫lengthCompare的函式
      bool b2 = (*pf)("hello", "goodbye"); // 一個等價的呼叫
      bool b3 = lengthCompare("hello", "goodbye"); // 另一個等價的呼叫
    
      string::size_type sumLength(const string &, const string &);
      bool cstringCompare(const char *, const char *);
      pf = 0; // 正確:pf不指向任何函式
      pf = sumLength; // 錯誤:回傳型別不匹配
    
  10. 編譯器通過指標型別決定選用哪個函式,指標型別必須與多載函式中的某一個精確匹配
  11. 和陣列類似,雖然不能定義函式型別的形參,但是形參可以是指向函式的指標,此時,形參看起來是函式型別,實際上確是當成指標使用,我們可以直接把函式作為實參使用,此時它會自動轉換成指標,
      // 第三個形參是函式型別,它會自動的轉換成指向函式的指標
      void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));
      // 等價的宣告:顯式地將形參定義成指向函式的指標
      void useBigger(const string &s1, const string &s2, bool(*pf)(const string &, const string &));
      // 自動將函式lengthCompare轉換成指向該函式的指標
      useBigger(s1, s2, lengthCompare); 
    
  12. 型別別名和decltype能讓我們簡化使用了函式指標的代碼,decltype回傳函式型別,此時不會將函式型別自動轉換成指標型別,
      // Func和Func2是函式型別
      typedef bool Func(const string&, const string&);
      typedef decltype(lengthCompare) Func2; // 等價的型別
      // FuncP和FuncP2是指向函式的指標
      typedef bool(*FuncP)(const string&, const string&);
      typedef decltype(lengthCompare) *FuncP2; // 等價的型別
    
      // useBigger的等價宣告,其中使用了型別別名,這兩個宣告陳述句宣告的是同一個函式,
      void useBigger(const string&, const string&, Func); // 編譯器自動地將Func表示的函式型別轉換成指標
      void useBigger(const string&, const string&, FuncP2);
    
  13. 和陣列類似,雖然不能回傳一個函式,但是能回傳指向函式型別的指標,然而,我們必須把回傳型別寫成指標形式,編譯器不會自動地將函式回傳型別當成對應的指標型別處理,
      using F = int(int*, int); // F是函式型別,不是指標
      using PF = int(*)(int*, int); // PF是指標型別
      
      // 1. 使用型別別名宣告f1
      PF f1(int); // 正確:PF是指向函式的指標,f1回傳指向函式的指標
      F f1(int); // 錯誤:F是函式型別,f1不能回傳一個函式
      F *f1(int); // 正確:顯示地指定回傳型別是指向函式的指標
    
      // 2. 直接宣告f1
      int (*f1(int))(int*, int); 
    
      // 3. 使用尾置回傳型別的方式宣告f1
      auto f1(int) -> int (*)(int*, int); 
    
      // 4. 使用auto和decltype用于函式指標型別
      string::size_type sumLength(const string&, const string&);
      string::size_type largerLength(const string&, const string&);
      // 牢記當我們將decltype作用于某個函式時,它回傳函式型別而非指標型別,
      decltype(sumLength) *getFcn(const string &); // 使用decltype(sumLength)和decltype(largerLength)一樣
    
  14. 實參(argument),形參(parameter)
  15. 隱藏名字:某個作用域內宣告的名字會隱藏掉外層作用域中宣告的同名物體(不僅限于變數的名字),
  16. 行內函式:請求編譯器在可能的情況下在呼叫點展開函式,行內函式可以避免常見的函式呼叫開銷,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251333.html

標籤:C++

上一篇:C/C++編程筆記:Switch陳述句詳解,知識點+代碼示例

下一篇:C++ STL 優先佇列 (priority_queue)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more