C++入門04 函數的參數傳遞、引用類型與重載

???

圖源:文心一言

聽課筆記簡單整理,供小伙伴們參考,包含以下內容“🐋3.11 引用類型、🐋3.14 內聯函數、🐋3.15 默認參數值、🐋3.16 函數重載、🐋3.17 C++系統函數”~🥝🥝

  • 第1版:聽課的記錄代碼~🧩🧩

編輯:梅頭腦🌸

審核:文心一言


目錄

🐳課程來源

🐳函數

🐋3.11 引用類型

🐋3.14 內聯函數

🐋3.15 默認參數值

🐋3.16 函數重載

🐋3.17 C++系統函數

🔚結語


🐳課程來源

  • 鄭莉老師的公開課:🌸C++語言程序設計基礎 - 清華大學 - 學堂在線 (xuetangx.com)

🐳函數

🐋3.11 引用類型

🧩題目

輸入兩個整數交換后輸出(值傳遞)

📇算法思路

因為返回值只能返回1個值,而不能返回2個數字交換過的值,所以這個題目使用引用。

??算法代碼

#include <iostream>
using namespace std;void swap(int& a, int& b) {int t = a;a = b;b = t;
}int main()
{int x = 5, y = 10;cout << "x = " << x << ", y = " << y << endl;swap(x, y);cout << "x = " << x << ", y = " << y << endl;return 0;
}

📇執行結果

?

📇代碼解釋

當進行值交換時,注意函數聲明?void swap(int& a, int& b)。如果修改為?void swap(int a, int b),則無法完成值的交換功能。原因是,在后一種情況下,a?和?b?是通過值傳遞的,即傳遞的是?x?和?y?的副本。雖然在?swap?函數內部更改了?a?和?b?的值,但這些更改不會影響到原始的?x?和?y

而通過在參數前加上引用符號?&,我們實際上傳遞的是?x?和?y?的地址。這樣,在函數內部對?a?和?b?所做的任何修改都會直接反映在原始的?x?和?y?上,從而實現了值的交換。

引用在C++中是一個很有用的特性,它提供了對變量的直接別名訪問,而不是通過指針的間接訪問。雖然引用在某些情況下可能引發安全問題(比如懸掛引用,即引用了一個已經被銷毀的對象的引用),但這并不意味著引用本身不安全或應該避免使用。相反,當正確使用時,引用可以提高代碼的可讀性和效率。

以下是一些推薦使用引用的場景:

  1. 函數參數:當你想在函數內部修改傳遞進來的變量時,引用是一個很好的選擇。通過傳遞引用而不是值,你可以避免復制的開銷,并且函數可以直接修改原始數據。

  2. 返回值:雖然通常建議通過值返回小型對象,但對于大型對象或容器(如std::vectorstd::string等),通過引用返回可能更有效。然而,需要注意的是,你不能返回局部變量的引用,因為局部變量在函數返回后會被銷毀,導致懸掛引用。在這種情況下,你應該返回一個新對象或傳遞一個輸出參數。

  3. 避免復制開銷:當處理大型對象或數據結構時,通過引用傳遞它們可以避免復制整個對象的開銷。

  4. 多態性:在面向對象編程中,引用經常與基類和派生類一起使用,以實現多態行為。通過基類引用調用虛函數時,會調用相應對象類型的實現。

  5. 范圍基于的for循環:C++11引入了范圍基于的for循環,它使用引用來遍歷容器中的元素,避免了不必要的復制。

  6. 性能優化:在某些性能關鍵的場景中,使用引用可以避免不必要的內存分配和釋放,從而提高程序的性能。

然而,需要注意的是,過度使用引用也可能導致代碼難以理解和維護。因此,在使用引用時應該權衡其優點和潛在的復雜性。

🐋3.14 內聯函數

🧩題目

計算圓的面積。

📇算法思路

本例僅涉及到乘法,為了提高計算效率,使用內聯函數。

??算法代碼

#include <iostream>
using namespace std;const double PI = 3.14159265358979;
inline double calArea(double radius) {return PI * radius * radius;
}int main()
{double r = 3.0;double area = calArea(r);cout << area << endl;return 0;
}

📇執行結果

?

📇代碼解釋

本行代碼?inline double calArea(double radius)?中的?inline?關鍵字表明?calArea?函數是一個內聯函數。

內聯函數(Inline Function)是C++中的一種函數優化技術。通過在函數聲明前添加inline關鍵字,開發者可以建議編譯器將函數的調用替換為函數體本身的代碼,這種替換通常發生在編譯時期。內聯函數的目的是減少函數調用的開銷,提高程序的執行效率。

內聯函數的特點:

  1. 內聯替換:內聯函數的代碼通常會被直接插入到調用點(可以簡單理解為函數直接粘在main函數中執行),從而消除函數調用的開銷,如參數壓棧、跳轉到函數體、執行函數后返回等。
  2. 編譯時期決定:是否真正內聯一個函數是由編譯器在編譯時期決定的。inline關鍵字只是對編譯器的建議,編譯器可以選擇忽略它(具體來說,比較機智的編譯器可以自己識別哪些適合作為內聯函數編譯,哪些不適合)。
  3. 定義在頭文件中:由于內聯函數的代碼需要在每個調用點都可用,因此內聯函數通常定義在頭文件中,以便在包含該頭文件的每個源文件中都可見。
  4. 適用于小型函數:內聯最適合那些體積小、執行速度快且調用頻繁的函數。對于大型函數,內聯可能會導致代碼膨脹,反而降低性能。
  5. 無函數調用開銷,但有代碼膨脹風險:內聯可以避免函數調用的開銷,但如果一個函數被內聯多次,它的代碼就會在最終的可執行文件中出現多次,導致代碼膨脹。

使用內聯函數的注意事項:

  • 內聯函數應該簡潔且執行快速,避免包含循環和遞歸調用
  • 避免在頭文件中定義大型的內聯函數,這會導致包含該頭文件的每個源文件都包含該函數的完整代碼,增加編譯時間和最終可執行文件的大小。
  • 謹慎使用內聯,特別是在性能敏感的代碼中。通過性能測試和剖析來確定是否真的需要內聯某個函數。

🐋3.15 默認參數值

🧩題目

計算長方體的體積。

📇算法思路

emm...長方體的體積 = 長 x 寬 x 高 這樣子...

??算法代碼

#include <iostream>
#include <iomanip>
using namespace std;int getVolume(int length, int width = 3, int height = 3);int main()
{const int X = 10, Y = 12, Z = 15;cout << "Some box data is ";cout << getVolume(X, Y, Z) << endl;cout << "Some box data is ";cout << getVolume(X, Y) << endl;cout << "Some box data is ";cout << getVolume(X) << endl;return 0;
}int getVolume(int length, int width, int height) {cout << setw(5) << length << setw(5) << width << setw(5) << height << '\t';return length * width * height;
}

📇執行結果

?

📇代碼解釋

  • int getVolume(int length, int width = 3, int height = 3); 這段代碼,表示 width 與 height均有默認初始值,但用戶也可以自行輸入 width 與 height 的參數覆蓋這2個默認值,例如:
  • cout << getVolume(X, Y, Z) << endl; 這段代碼,傳入?length = X = 10,width = Y = 12,height = Z = 15;
  • cout << getVolume(X, Y) << endl; 這段代碼,傳入?length = X = 10,width = Y = 12,height = 3(默認值);
  • cout << getVolume(X) << endl; 這段代碼,傳入?length = X = 10,width = 3(默認值),height = 3(默認值);

注意:

  • 默認參數的順序:默認參數必須從右到左連續。也就是說,如果一個參數有默認值,那么它右邊的所有參數也都必須有默認值。例如:

int func(int a, int b = 10, int c = 20); // 合法
int func(int a = 10, int b, int c = 20); // 錯誤!'b' 沒有默認值,但 'a' 有。
  • 默認參數與函數重載:默認參數可以被視為函數重載的一種簡化形式。但是,當同時使用默認參數和函數重載時,需要注意可能產生的歧義。編譯器會優先選擇參數最匹配的函數,而不是選擇有更多默認參數的函數。
  • 默認參數的值:默認參數的值可以是常量、全局變量,甚至可以是函數。但是,默認參數的值在函數聲明時確定,而不是在函數調用時確定。因此,如果默認參數是一個變量,那么該變量的值將是函數聲明時的值,而不是函數調用時的值。
  • 默認參數在頭文件中定義:通常,函數的聲明放在頭文件中,而函數的定義放在源文件中。當使用默認參數時,應將默認參數放在函數聲明中(即在頭文件中),而不是在函數定義中。這樣可以確保所有包含該頭文件的源文件都能看到相同的默認參數。

🐋3.16 函數重載

🧩題目

求 整數、浮點數的平方和。?

📇算法思路

功能相同,但僅參數類型與返回類型不同的兩個函數,可以使用函數重載(使用同一個名稱),以方便程序員的調用。

??算法代碼

#include <iostream>
using namespace std;int sumOfSquare(int a, int b) {return a * a + b * b;
}
double sumOfSquare(double a, double b) {return a * a + b * b;
}int main()
{int m, n;cout << "Enter two integer:";cin >> m >> n;cout << "Their sum of square:" << sumOfSquare(m, n) << endl;double x, y;cout << "Enter two real number:";cin >> x >> y;cout << "Their sum of square:" << sumOfSquare(x, y) << endl;return 0;
}

📇執行結果

輸入整數:3 5,浮點數:3.5 5.5的執行結果:

📇代碼解釋

int sumOfSquare(int a, int b) double sumOfSquare(double a, double b) ,函數名相同,但是參數類型與返回類型不同,屬于函數重載。

函數重載是指在同一作用域內,可以有一組具有相同名字但參數數量或類型不同的函數。編譯器會根據調用時提供的參數數量和類型來選擇最合適的函數進行調用。

函數重載的注意事項:

  1. 參數差異:重載的函數必須通過參數的數量、類型或順序來區分。僅僅返回類型的不同并不足以構成重載。

  2. 最佳匹配:當調用重載函數時,編譯器會嘗試找到與提供的參數最匹配的函數。如果沒有找到確切匹配,編譯器可能會嘗試通過隱式類型轉換來找到匹配,這可能會導致不期望的行為。

  3. 避免歧義:設計重載函數時,要確保不會出現歧義性調用。例如,如果兩個重載函數都可以通過隱式類型轉換來匹配同一組參數,編譯器將無法決定應該調用哪一個,從而導致編譯錯誤。對于重載函數,每個重載都應該有清晰的文檔和注釋,說明它的用途、參數和返回值。這有助于其他開發者理解和使用這些函數。

  4. 謹慎使用默認參數:默認參數和函數重載在某些情況下可以互換使用,但它們有不同的優缺點。使用默認參數可以減少需要編寫的函數數量,但可能會使函數簽名變得復雜。而函數重載可以提供更清晰的語義,但可能會導致更多的代碼重復。在選擇時,應根據具體情況權衡利弊。

🐋3.17 C++系統函數

🧩題目

求 特定角度的三角函數計算值。?

📇算法思路

調用庫函數 cmath 中的 sin、cos、tan~

??算法代碼

#include <iostream>
#include <cmath>
using namespace std;
const double PI = 3.14159265358979;int main()
{double angle;cout << "Please enter an angle:";cin >> angle;double radian = angle * PI / 180;cout << "sin(" << angle << ") = " << sin(radian) << endl;cout << "cos(" << angle << ") = " << cos(radian) << endl;cout << "tan(" << angle << ") = " << tan(radian) << endl;return 0;
}

📇執行結果

輸入整數:30 的執行結果:

📇知識擴展

C++常用庫

C++ 標準庫提供了大量的函數和類,用于處理各種常見的編程任務。以下是一些 C++ 中常用的庫函數和它們所屬的庫:

輸入/輸出流庫 (iostream)

  • std::cin: 用于從標準輸入讀取數據。
  • std::cout: 用于向標準輸出寫入數據。
  • std::cerr: 用于向標準錯誤輸出寫入數據。
  • std::clog: 用于向標準日志輸出寫入數據。

字符串庫 (string)

  • std::string: 表示字符串的類。
  • std::getline(): 從輸入流中讀取一行文本。
  • std::stoi(),?std::stol(),?std::stoll(): 將字符串轉換為整數。
  • std::stof(),?std::stod(),?std::stold(): 將字符串轉換為浮點數。

容器庫 (vector, map, set, etc.)

  • std::vector: 可動態調整大小的數組。
  • std::map: 關聯數組,存儲鍵值對。
  • std::set: 存儲唯一元素的集合。
  • std::unordered_map,?std::unordered_set: 無序的 map 和 set。

算法庫 (algorithm)

  • std::sort(): 對容器中的元素進行排序。
  • std::find(): 在容器中查找元素。
  • std::binary_search(): 對已排序的容器進行二分查找。
  • std::transform(): 對容器中的元素進行轉換。

數值庫 (numeric)

  • std::accumulate(): 計算容器中元素的累積和或其他二元操作的累積結果。
  • std::inner_product(): 計算兩個容器的內積。
  • std::iota(): 為容器中的元素填充連續的遞增值。

文件流庫 (fstream)

  • std::ifstream: 用于從文件讀取數據的輸入文件流。
  • std::ofstream: 用于向文件寫入數據的輸出文件流。
  • std::fstream: 可用于讀寫文件的文件流。

時間庫 (chrono)

  • std::chrono::system_clock: 獲取系統時間。
  • std::chrono::steady_clock: 獲取穩定的時間間隔,不受系統時間調整影響。
  • std::chrono::duration_cast(): 轉換時間間隔的精度。

線程庫 (thread)

  • std::thread: 表示線程的類。
  • std::this_thread::sleep_for(): 使當前線程休眠指定的時間間隔。
  • std::mutex: 互斥鎖,用于同步線程。

異常處理庫 (exception)

  • std::exception: 所有標準異常的基類。
  • std::throw_with_nested(): 拋出嵌套異常。
  • std::rethrow_if_nested(): 重新拋出嵌套異常(如果有)。

其他常用庫

  • std::random: 用于生成隨機數。
  • std::regex: 用于正則表達式匹配和操作。
  • std::atomic: 用于多線程編程中的原子操作。
  • std::optional: 表示可能包含值或為空的包裝器。

這只是 C++ 標準庫中的一小部分。實際上,C++ 標準庫非常龐大,提供了各種各樣的功能來支持各種編程需求。在使用這些庫時,建議查閱相關的文檔和參考資料以獲取更詳細的信息和示例代碼。


🔚結語

博文到此結束,寫得模糊或者有誤之處,期待小伙伴留言討論與批評,督促博主優化內容{例如有錯誤、難理解、不簡潔、缺功能}等,博主會頂鍋前來修改~~😶?🌫?😶?🌫?

我是梅頭腦,本片博文若有幫助,歡迎小伙伴動動可愛的小手默默給個贊支持一下,感謝點贊小伙伴對于博主的支持~~🌟🌟

同系列的博文:🌸數據結構_梅頭腦_的博客-CSDN博客

同博主的博文:🌸隨筆03 筆記整理-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/696582.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696582.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696582.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LabVIEW多通道壓力傳感器實時動態檢測

LabVIEW多通道壓力傳感器實時動態檢測 介紹了一種基于LabVIEW的多通道壓力傳感器實時動態檢測系統&#xff0c;解決壓阻式壓力傳感器溫度補償過程的復雜度&#xff0c;提高測量的準確性。通過自動輪詢檢測方法&#xff0c;結合硬件檢測模型和多通道檢測系統設計&#xff0c;本…

集合框架之List集合

目錄 ?編輯 一、什么是UML 二、集合框架 三、List集合 1.特點 2.遍歷方式 3.刪除 4.優化 四、迭代器原理 五、泛型 六、裝拆箱 七、ArrayList、LinkedList和Vector的區別 ArrayList和Vector的區別 LinkedList和Vector的區別 一、什么是UML UML&#xff08;Unif…

基于ORB-SLAM2與YOLOv8剔除動態特征點(三種方法)

基于ORB-SLAM2與YOLOv8剔除動態特征點(三種方法) 寫上篇文章時測試過程比較亂&#xff0c;寫的時候有些地方有點失誤&#xff0c;所以重新寫了這篇 本文內容均在RGB-D環境下進行程序測試 本文涉及到的動態特征點剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…

系統學習Python——裝飾器:類裝飾器-[單例類:編寫替代方案]

分類目錄&#xff1a;《系統學習Python》總目錄 有趣的是&#xff0c;這里如果能使用nonlocal語句&#xff08;僅在Python3.X中可用&#xff09;來改變外層作用域名稱&#xff0c;我們在這里可以編寫一個自包含程度更高的解決方案一一一下面的替代方案為每個類使用了一個外層作…

編寫程序,實現shell功能——項目訓練——day08

c c今天做了一個實戰項目訓練&#xff0c;編寫一個程序&#xff0c;實現shell功能&#xff0c;我們稱之為minishell。 主要是利用Linux中IO接口實現&#xff0c;實現的功能有&#xff1a; 1.ls ls -a ls -l cd cp mv pwd c…

軟件License授權原理

軟件License授權原理 你知道License是如何防止別人破解的嗎&#xff1f;本文將介紹License的生成原理&#xff0c;理解了License的授權原理你不但可以防止別人破解你的License&#xff0c;你甚至可以研究別人的License找到它們的漏洞。喜歡本文的朋友建議收藏關注&#xff0c;…

【Linux】進程狀態

進程狀態 進程狀態的簡要介紹運行狀態進程排隊 阻塞狀態掛起狀態Linux中的進程狀態 進程狀態的簡要介紹 進程狀態指的是一個操作系統中正在運行的進程當前所處的狀態。根據不同的操作系統&#xff0c;進程狀態可能會有一些細微的差別&#xff0c;但最主要的是以下三種狀態 運行…

Java——方法的使用

目錄 一.方法的概念及使用 1 什么是方法(method) 2.方法定義 3 方法調用的執行過程 4 實參和形參的關系(重要) 5.沒有返回值的方法 二.方法重載 1.為什么需要方法重載 2.方法重載概念 3.方法簽名 三.遞歸 1.遞歸的概念 2.遞歸執行過程分析 3. 遞歸練習 一.方法的…

貓頭虎分享已解決Bug || 容器編排問題:OrchestrationFailure, ContainerManagementError

博主貓頭虎的技術世界 &#x1f31f; 歡迎來到貓頭虎的博客 — 探索技術的無限可能&#xff01; 專欄鏈接&#xff1a; &#x1f517; 精選專欄&#xff1a; 《面試題大全》 — 面試準備的寶典&#xff01;《IDEA開發秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鴻蒙》 …

代碼隨想錄算法訓練營第四十二天|122. 買賣股票的最佳時機 II

674. 最長連續遞增序列 public static int findLengthOfLCIS(int[] nums) {int[] dp new int[nums.length];dp[0] 1;for (int i 1; i < nums.length; i) {dfs(nums, dp, i);}Arrays.sort(dp);return dp[dp.length - 1];}public static void dfs(int[] nums, int[] dp, i…

【Python】【VS Code】VS Code中python.json和setting.json文件配置說明

目錄 1. python.json配置 2. setting.json配置 3. 解決中文亂碼 4. 實現效果 1. python.json配置 python.json 獲取步驟&#xff1a;文件 -> 首選項 -> 配置用戶代碼片段 -> python 此為VS Code的頭文件設置&#xff0c;復制以下內容到 python.json {"HEADER…

個人做抖店如何能夠快速起店?掌握好技巧是關鍵!建議收藏!

大家好&#xff0c;我是電商小布。 相信我們每個朋友在店鋪開通后&#xff0c;最關心的事情就是小店成功起店了。 那么個人做抖店想要快速起店&#xff0c;該怎么來進行操作呢&#xff1f; 接下來&#xff0c;小布重點給大家說三點&#xff1a; 首先來說一下小店的主體類型…

git常用命令記錄

1、第一次初始化 git init git add . git commit -m ‘first commit’ git remote add origin gitgithub.com:帳號名/倉庫名.git git pull origin master git push origin master # -f 強推 git clone gitgithub.com:git帳號名/倉庫名.git 2、工作基本操作 git checkout master…

dell r740服務器黃燈閃爍維修現場解決

1&#xff1a;首先看一下這款DELL非常主力的PowerEdge R740服務器長啥樣&#xff0c;不得不說就外觀來說自從IBM拋棄System X系列服務器后&#xff0c;也就戴爾這個外觀看的比較順眼。 圖一&#xff1a;是DELL R740前視圖&#xff08;這款是8盤機型&#xff09; 圖二&#xff…

QT 數據庫的增加操作和畫圖 Win

第一步、先配置CMakeLists.txt 在CMakeLists.txt中添加 find_package(Qt6 REQUIRED COMPONENTS Sql) find_package(Qt6 REQUIRED COMPONENTS Charts)target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Sql) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Charts)避…

springboot集成JWT實現token權限認證

vuespringboot登錄與注冊功能的實現 注&#xff1a;對于JWT的學習&#xff0c;首先要完成注冊和登錄的功能&#xff0c;本篇博客是基于上述博客的進階學習&#xff0c;代碼頁也是在原有的基礎上進行擴展 ①在pom.xml添加依賴 <!-- JWT --> <dependency><grou…

Linux篇:Shell命令以及運行原理 和 權限

一. Shell命令及原理 Linux操作系統狹義上是Linux內核&#xff0c;廣義上是指Linux內核Linux外殼(Shell)和對應的配套程序 Linux外殼&#xff1a;Linux 外殼是用戶與內核之間的接口&#xff0c;用戶通過外殼與操作系統進行交互和操作。在 Linux 系統中&#xff0c;用戶可以選…

C語言——static的三大用法

被稱為面試愛考愛問題的它到底有何奧義 它難度不大并且非常常用&#xff0c;話不多說&#xff0c;直接開始 一、局部靜態變量 定義 在函數內部使用static修飾的變量被稱為局部靜態變量&#xff0c;與普通的局部變量不同&#xff0c;局部靜態變量在使用后不會被銷毀&#xff…

pycharm 遠程運行報錯 Failed to prepare environment

什么也沒動的情況下&#xff0c;遠程連接后運行是沒問題的&#xff0c;突然在運行時就運行不了了&#xff0c;解決方案 清理緩存&#xff1a; 有時候 PyCharm 的內部緩存可能出現問題&#xff0c;可以嘗試清除緩存&#xff08;File > Invalidate Caches / Restart&#xff0…

mysql優化指南之原理篇

之前碰到一個線上問題&#xff0c;在接手一個同事的項目后&#xff0c;因為工期比較趕&#xff0c;我還沒來得及了解業務背景和大致實現&#xff0c;只是了解了上線發布的順序和驗證方式就進行了上線&#xff0c;在上線進行金絲雀的時候系統還沒發生什么異常&#xff0c;于是我…