C++基礎篇(2)

目錄

前言

1.缺省參數

2.函數重載

?2.1函數重載的基本規則

?編輯2.2注意事項

2.3 重載解析(Overload Resolution)--補充內容

3.引用

3.1引用的概念和定義

3.2引用的特性

3.3引用的使用

3.4const引用

4.指針和引用的關系

結束語

前言

上節小編講解了命名空間和函數的輸入輸出,本節將講解缺省參數,函數重載等知識。

1.缺省參數

缺省參數是聲明或定義函數時為函數的參數指定一個缺省值。在調用該函數時,如果沒有指定實參,則采用該形參的缺省值,否則使用指定的實參,缺省參數分為全缺省和半缺省參數。(有些地方把缺省參數也叫默認參數)
全缺省就是全部形參給缺省值,半缺省就是部分形參給缺省值。C++規定半缺省參數必須從右往左
依次連續缺省,不能間隔跳躍給缺省值。
例如(錯誤示范)
void func(int a, double b = 3.14, const char* c = "default") { // 正確// 函數體
}void func(int a = 1, double b, const char* c = "default") { // 錯誤,不能跳過 b// 函數體
}
#include <iostream>
using namespace std;
void func(int x=0) {cout << x << endl;
}
int main() {
// 沒有傳參時,使?參數的默認值
// 傳參時,使?指定的實參func();func(10);return 0;
}

運行結果:

0

10

帶缺省參數的函數調用,C++規定必須從左到右依次給實參,不能跳躍給實參。
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
int main()
{Func1();Func1(1);Func1(1, 2);Func1(1, 2, 3);Func2(100);Func2(100, 200);Func2(100, 200, 300);Func2(100, ,300);//錯誤return 0;
}

03e0f99269104ad9857a995b841d7c85.png

函數聲明和定義分離時,缺省參數不能在函數聲明和定義中同時出現,規定必須函數聲明給缺省
值。
// 在頭文件中的函數聲明
void func(int a = 1, double b = 3.14, const char* c = "default");// 在源文件中的函數定義
void func(int a, double b, const char* c) {// 函數體
}

2.函數重載

在C++中,函數重載(Function Overloading)是指在同一作用域內可以存在多個同名函數,但這些函數的參數列表(參數的個數、類型或者順序)必須不同。編譯器會根據傳遞給函數的參數來決定調用哪一個重載版本。

?2.1函數重載的基本規則
?

1.參數數量不同:函數可以具有不同數量的參數。

#include <iostream>
using namespace std;
int Add(int a, int b) {return a + b;
}int Add(int a, int b, int c) { return a + b + c;
}int main() {int sum1 = Add(10, 20);   double sum2 = Add(10,20,30); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}

7a6272792b2f45329a1ae531db18f8ee.png
2. 參數類型不同:函數可以具有不同類型的參數。

#include <iostream>
using namespace std;
int add(int a, int b) {cout << "int add(int a, int b)"<<endl;return a + b;}
double add(double a, double b) {cout << "double add(double a, double b)"<<endl;return a + b;}
int main() {int sum1 = add(10, 20);   double sum2 = add(1.5, 2.5); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}

f1f6cddca9174c738581aee06c9f704e.png
3. 參數順序不同:如果參數類型相同,但順序不同,也可以構成重載。

#include <iostream>
using namespace std;
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
int main() {f(10, 'c');f('c', 10);return 0;
}

668ff08bb9574e458d0164b9479f4544.png

2.2注意事項

- 返回類型:函數重載與返回類型無關,即不能僅通過改變返回類型來重載函數。
-默認參數:使用默認參數的函數可能會導致重載解析的歧義,應當小心使用。

int Add(int a, int b) {return a + b;
}double Add(int a, int b) { // 錯誤:不能僅通過返回類型來重載return static_cast<double>(a + b);
}
#include <iostream>
using namespace std;// 下?兩個函數構成重載
// f()但是調?時,會報錯,存在歧義,編譯器不知道調?誰
void f()
{cout << "f()" << endl;
}
void f(int a = 10)
{cout << "f(int a)" << endl;
}
int main() {f();return 0;
}

fd43ff7a5a1a4f20832734c981822d9e.png

2.3 重載解析(Overload Resolution)--補充內容

當調用一個重載函數時,編譯器會根據提供的實參和每個重載函數的形參列表進行匹配,以確定調用哪一個函數。這個過程稱為重載解析。如果編譯器無法明確地確定應該調用哪個函數,或者找到多個合適的匹配,就會產生編譯錯誤。

函數重載是C++多態性的一種形式,它允許程序員使用相同的名字來執行相似的操作,這增強了代碼的清晰性和可讀性。

3.引用

3.1引用的概念和定義

在 C++ 中,引用是一個變量的別名。一旦一個引用被初始化為指向一個對象,它就不能被重新綁定到另一個對象。這與指針不同,指針可以在任何時候指向不同的對象。

引用的概念

  • 別名:引用為另一個變量提供了一個額外的名字,它和原變量指向相同的內存位置。
  • 不可變性:一旦引用被初始化,它就不能被重新賦值為另一個變量的引用。
  • 無需解引用:使用引用時,不需要像指針一樣使用?*?操作符來訪問引用的值。
  • 效率:引用在傳遞參數時可以避免不必要的復制,特別是對于大型對象來說,使用引用可以提高效率。

引用的定義

引用在 C++ 中是這樣定義的:

類型 &引用名 = 原變量名;

一些有趣的實例:

比如:水滸傳中李逵,宋江叫"鐵牛",江湖上人稱"黑旋風";林沖,外號豹子頭;

這里,類型?是原變量的類型,&?符號用于聲明引用,引用名?是你給引用起的名字,而?原變量名?是已經存在的變量。

1f4ad6d33e3f44d49138ef72580f55b2.png

#include <iostream>
using namespace std;
int main() {int a = 520;int& b = a;int& c = a;int& d = b;++d;
// 引?:b和c是a的別名cout << &a << endl;cout << &b << endl;cout << &c << endl;
// 也可以給別名b取別名,d相當于還是a的別名cout << &d << endl;
//地址,值都是一樣的cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;return 0;
}

e4fe0f1e22424434810ab50ad72d01dc.png

3.2引用的特性

? 引用在定義時必須初始化
? 一個變量可以有多個引用
? 引用一旦引用一個實體,再不能引用其他實體
#include<iostream>
using namespace std;
int main()
{int a = 10;// 編譯報錯:“ra”: 必須初始化引?//int& ra;int& b = a;int c = 20;// 這?并?讓b引?c,因為C++引?不能改變指向,// 這?是?個賦值b = c;cout << a << endl;cout << b << endl;cout << c << endl;b = 30;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << a << endl;cout << b << endl;cout << c << endl;return 0;
}

c4480a75ea4b458eb7c23cc2e3926981.png

3.3引用的使用

1.引用在實踐中主要是于引用傳參和引用做返回值中減少拷貝提高效率和改變引用對象時同時改變被引用對象。
2.引用傳參跟指針傳參功能是類似的,引用傳參相對更方便一些。
3.引用返回值的場景相對比較復雜,小編實力有限,以后等知識豐富了再會詳細講解。
4.引用和指針在實踐中相輔相成,功能有重疊性,但是各有特點,互相不可替代。C++的引用跟其他語言的引用(如Java)是有很大的區別的,除了用法,最大的點,C++引用定義后不能改變指向,java的引用可以改變指向。
5.一些主要用C代碼實現版本數據結構教材中,使用C++引用替代指針傳參,用的是簡化程序,避開復雜的指針。
代碼實例:
#include <iostream>
using namespace std;
void Swap(int& x, int& y) {int temp = x;x = y;y = temp;
}
int main() {int x = 520, y = 1314;cout << x << " " << y << endl;Swap(x, y);cout << x << " " << y << endl;return 0;
}

816ca5a6fbd5403c9824d39573ac5af3.png

#include<iostream>
#include <assert.h>
#include <stdlib.h> using namespace std;
typedef int STDataType;
typedef struct Stack {STDataType* a;int top;int capacity;
} ST;void STInit(ST& rs, int n = 4) {rs.a = (STDataType*)malloc(n * sizeof(STDataType));rs.top = 0; // 棧頂初始化為 0,表示棧為空rs.capacity = n;
}void STPush(ST& rs, STDataType x) {// 滿了,擴容if (rs.top == rs.capacity) {printf("擴容\n");int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("realloc fail");return;}rs.a = tmp;rs.capacity = newcapacity;}rs.a[rs.top] = x; rs.top++; // 棧頂指針上移
}int& STTop(ST& rs) {assert(rs.top > 0); // 確保棧不為空return rs.a[rs.top - 1]; // 返回棧頂元素的引用
}int main() {ST st1;STInit(st1);STPush(st1, 1);STPush(st1, 2);cout << STTop(st1) << endl; // 輸出棧頂元素 2STTop(st1) += 10; // 通過引用修改棧頂元素cout << STTop(st1) << endl; // 輸出修改后的棧頂元素 12return 0;
}

bc232eec8078412581694a024397c8b1.png

3.4const引用

在 C++ 中,const?引用是一種特殊類型的引用,它被用來引用一個對象,同時保證這個引用不會修改所引用的對象。這種引用通常用于函數參數,以允許函數讀取傳遞的對象,但不允許通過引用修改它。

以下是?const?引用的幾個關鍵點:

聲明?const?引用

const 類型 &引用名 = 引用的對象;

這里,類型?是被引用對象的類型,引用名?是你給引用起的名字,而?引用的對象?是你想要引用的實際對象。

使用?const?引用的好處

  • 保護數據不被修改:通過?const?引用,你可以確保傳遞給函數的參數不會被函數修改。
  • 可以引用臨時對象和字面量const?引用可以引用右值(如字面量或臨時對象),這是非?const?引用無法做到的。
  • 可以與任何類型的對象兼容:只要類型可以轉換為?const?引用的類型,就可以創建?const?引用。

示例

不需要注意的是類似 int& rb = a*3; double d = 12.34; int& rd = d; 這樣一些場景下a*3的和結果保存在一個臨時對象中, int& rd = d 也是類似,在類型轉換中會產生臨時對象存儲中間值,也就是時,rb和rd引用的都是臨時對象,而C++規定臨時對象具有常性,所以這里就觸發了權限放大,必須要用常引用才可以。
int main()
{
const int a = 10;
// 編譯報錯:error C2440: “初始化”: ?法從“const int”轉換為“int &”
// 這?的引?是對a訪問權限的放?
//int& ra = a;
// 這樣才可以
const int& ra = a;
// 編譯報錯:error C3892: “ra”: 不能給常量賦值
//ra++;
// 這?的引?是對b訪問權限的縮?
int b = 20;
const int& rb = b;
// 編譯報錯:error C3892: “rb”: 不能給常量賦值
//rb++;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 10;
const int& ra = 30;
// 編譯報錯: “初始化”: ?法從“int”轉換為“int &”
// int& rb = a * 3;
const int& rb = a*3;
double d = 12.34;
// 編譯報錯:“初始化”: ?法從“double”轉換為“int &”
// int& rd = d;
const int& rd = d;
return 0;
}

#include <iostream>
using namespace std;void print(const int& x) {cout << x << endl;// x = 5; // 錯誤:不能通過 const 引用修改對象
}int main() {int a = 10;const int& ref = a; // 創建一個對 a 的 const 引用// ref = 20; // 錯誤:不能通過 const 引用修改對象print(a); // 正確:傳遞 intprint(20); // 正確:傳遞字面量,通過 const 引用允許return 0;
}

注釋前的錯誤:

c0263619b1d34b908ea737dbd566f98b.png

正確運行結果:

dd74ed8c39d14563875c87faf1f56ec2.png

注意事項

  • 一旦?const?引用被初始化,它就不能再引用其他對象。
  • const?引用不能引用非?const?對象的地址,如果需要引用非?const?對象,必須顯式地聲明非?const?引用。

總之,const?引用在 C++ 中是一種非常有用的特性,它不僅提供了對數據的保護,還增加了代碼的靈活性和安全性。

4.指針和引用的關系

C++中指針和引用就像兩個性格迥異的親兄弟,指針是哥哥,引用是弟弟,在實踐中他們相輔相成,能有重疊性,但是各有自己的特點,互相不可替代。
? 語法概念上引用是一個變量的取別名不開空間,指針是存儲一個變量地址,要開空間。
? 引用在定義時必須初始化,指針建議初始化,但是語法上不是必須的。
? 引用在初始化時引用一個對象后,就不能再引用其他對象;而指針可以在不斷地改變指向對象。
? 引用可以直接訪問指向對象,指針需要解引用才是訪問指向對象。
? sizeof中含義不同,引用結果為引用類型的大小,但指針始終是地址空間所占字節個數(32位平臺下占4個字節,64位下是8byte)
? 指針很容易出現空指針和野指針的問題,引用很少出現,引用使用起來相對更安全一些。

結束語

本篇博客也就到此結束啦,C++ 的入門也差不多了,下個階段我們將步入類和對象的學習!!!
最后支持小編的友友和大佬們點個贊吧,也歡迎大家在評論區多多交流,感謝大家的支持!!!

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

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

相關文章

PlantUML 教程:繪制時序圖

繪制時序圖是 PlantUML 的一個強大功能&#xff0c;下面是詳細的 PlantUML 時序圖教程&#xff0c;幫助你理解如何使用它來創建清晰的時序圖。 基本概念 時序圖&#xff08;Sequence Diagram&#xff09;用于展示對象之間的交互以及它們之間的消息傳遞順序。它主要由以下元素…

感應燈光畫純電路開源版本

前言 之前那版燈光畫用的從垃圾佬淘的電路板拼出來的&#xff0c;功能不全&#xff0c;顯示效果不太好而且無法固定到相框上&#xff0c;這次改版用的嘉立創smt&#xff0c;貼了5片板子&#xff08;19元&#xff09;&#xff0c;功能上的改進是加了無極觸摸調光、添加了黃白兩…

簡易圖書管理系統——MYsql+Javase+JDBC

目錄 前言 數據表的建立 操作包各個類的實現 增加類 刪除類 展示類 借閱與歸還類 前言 書接上文 JDBC編程的學習——MYsql版本-CSDN博客 本期我們通過對先前圖書管理系統進行改造,是它的數據能保存在數據庫中 完整代碼我已經保存在github中,能不能給個星呢!!!! call…

debian固定ip

debian固定ip 前言 安裝好的Debian系統后&#xff0c;為了確保每次登陸的ip不變&#xff0c;需要固定 方法 命令如下 ip addr | grep inet因為有有線網和無線網 2 種連接方式&#xff0c;因此需要區別。 其中 enp 的是有線&#xff0c;wlp 的是無線 查看網關 IP 命令如下 …

互聯網末法時代的一些思考

這篇文章也是臨時起意&#xff0c;很長一段時間沒寫個人思考類的文章&#xff0c;主要原因也是時間完全不夠用。隨著年齡的增長&#xff0c;看待問題的視角也逐漸發生變化&#xff0c;例如從關注現象到關注動機&#xff0c;從關注結果到關注起因&#xff0c;2021年的時代我曾經…

java面向對象進階篇--static

一、前言 java進階篇已經開始了&#xff0c;先從面向對象開始&#xff0c;由于時間原因今天就只更新了static部分&#xff0c;內容上特別詳細&#xff0c;一些特別的注意事項也在反復的提醒大家。 溫馨提示一下&#xff0c;往后的java篇會越來越難&#xff0c;希望大家能夠堅…

P2p網絡性能測度及監測系統模型

P2p網絡性能測度及監測系統模型 網絡IP性能參數 IP包傳輸時延時延變化誤差率丟失率虛假率吞吐量可用性連接性測度單向延遲測度單向分組丟失測度往返延遲測度 OSI中的位置-> 網絡層 用途 面相業務的網絡分布式計算網絡游戲IP軟件電話流媒體分發多媒體通信 業務質量 通過…

運維檢查:mysql表自增id是否快要用完

數據庫表中最大自增ID用完會報錯。判斷是否接近或達到自增ID類型的最大值&#xff1a;? 對于MySQL中的自增ID&#xff0c;?如果使用的是int類型&#xff0c;?其無符號&#xff08;?unsigned&#xff09;?的最大值可以達到2^32 - 1&#xff0c;?即4294967295。?如果使用的…

python編程:從入門到實踐(第三版) 筆記

文章目錄 資源網站:https://www.ituring.com.cn/book/3038配置VSCode推薦資源網站推薦資源網址 資源網站:https://www.ituring.com.cn/book/3038 配置VSCode 推薦資源網站 推薦資源網址 英文版主頁&#xff1a; https://ehmatthes.github.io/pcc_3e 中文版主頁&#xff1a; h…

上市公司企業共同機構所有權數據、機構交叉持股數據(2005-2023)

數據來源&#xff1a;基礎數據來源于上市公司企業年報 時間跨度&#xff1a;2005-2023年 數據范圍&#xff1a;企業層面 數據指標&#xff1a; 參考《中國工業經濟》杜勇&#xff08;2021&#xff09;老師的做法&#xff0c;從 3 個維度構造指標反映上市公司共同機構所有權&…

Vue和Element UI 路由跳轉

在Vue.js中&#xff0c;使用Vue Router可以方便地實現頁面之間的路由跳轉。Element UI是一個基于Vue 2.0的桌面端組件庫&#xff0c;它本身并不直接提供路由跳轉的功能&#xff0c;但你可以在使用Element UI的Vue項目中結合Vue Router來實現這一功能。 以下是一個基于Vue和Ele…

Proxyman for Mac v5.6.1 抓包調試工具

Mac分享吧 文章目錄 效果一、下載軟件二、功能三、開始安裝1、雙擊運行軟件&#xff0c;將其從左側拖入右側文件夾中&#xff0c;等待安裝完畢2、應用程序顯示軟件圖標&#xff0c;表示安裝成功 四、運行測試1、打開軟件 安裝完成&#xff01;&#xff01;&#xff01; 效果 一…

【華為OD筆試】2024D卷命題規律解讀【分析300+場OD筆試考點總結】

可上 歐弟OJ系統 練習華子OD、大廠真題 綠色聊天軟件戳 od1441了解算法沖刺訓練&#xff08;備注【CSDN】否則不通過&#xff09; 文章目錄 相關推薦閱讀華為OD筆試2024D卷命題規律解讀華為OD算法/大廠面試高頻題算法練習沖刺訓練 相關推薦閱讀 【華為OD筆試】2024D卷機考套題…

C# Opencv實現本地以圖搜圖

地址&#xff1a;馮騰飛/本地以圖搜圖

Java面試八股之Redis哨兵機制

Redis哨兵機制 Redis Sentinel&#xff08;哨兵&#xff09;模式是一種高可用解決方案&#xff0c;用于監控和自動故障轉移Redis主從集群。以下是對哨兵模式詳細過程的描述&#xff1a; 1. 初始化與配置 部署哨兵節點&#xff1a;在不同的服務器上部署一個或多個Redis Sentin…

《算法筆記》總結No.7——二分(多例題詳解版)

一.二分查找 目前有一個有序數列&#xff0c;舉個例子&#xff0c;假設是1~1000&#xff0c;讓我們去查找931這個數字&#xff0c;淺顯且暴力的做法就是直接從頭到尾遍歷一遍&#xff0c;直到找到931為止。當n非常大&#xff0c;比如達到100w時&#xff0c;這是一個非常大的量級…

Linux 線程初步解析

1.線程概念 在一個程序里的一個執行路線就叫做線程&#xff08;thread&#xff09;。更準確的定義是&#xff1a;線程是“一個進程內部的控制序列。在linux中&#xff0c;由于線程和進程都具有id,都需要調度等等相似性&#xff0c;因此都可以用PCB來描述和控制,線程含有PCB&am…

美聯儲降息應該更早?高盛:有充分理由7月降息,而非9月

KlipC報道&#xff1a;高盛首席經濟學家哈祖斯Jan Hatzius表示&#xff0c;美聯儲“有充分理由”在7月會議上降息&#xff0c;而非等到9月。 在最新發布的報告中&#xff0c;他表明通脹已經取得了足夠的進展&#xff0c;回到了美聯儲2%的長期目標附近&#xff0c;這將使美聯儲…

[C++ 入門基礎 - 命名空間]

在C中&#xff0c;命名空間&#xff08;Namespace&#xff09;是一種用來組織代碼并避免命名沖突的機制。命名空間可以包含變量、函數、類等C中的所有實體&#xff0c;使得這些實體的名稱在命名空間內部有效&#xff0c;避免了與其他命名空間或全局作用域中相同名稱的沖突。 文…

實現將Nginx的每個網站配置單獨的訪問日志

一、問題描述 Nginx默認的訪問日志是不會區分哪個網站有哪些日志的,全部糅雜在一起;如果需要哪個網站有哪些訪問日志記錄,還需要將訪問日志下載下來后篩選,比較麻煩;希望將每個網站對應的日志能夠單獨記錄到對應的日志文件里面,方便排查和管理。 # 進入Nginx默認的日志文…