C++相關基礎概念之入門講解(下)

1. 引用

?
int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}
引用 不是新定義一個變量,而 給已存在變量取了一個別名 ,編譯器不會為引用變量開辟內存空
間,它和它引用的變量 共用同一塊內存空間(初期這么理解就好,實際上在底層是開了空間的)
引用的使用方法就是:類型 & 引用變量名 ( 對象名 ) = 引用實體;
舉個例子:

在這個代碼里面aa是a的別名,aa++了,也就是a++;所以這里的輸出是11;

舉個例子,現在有一個人叫小明,我們給他取一個別名叫明明,明明去吃飯了,那是不是小明也去吃飯了,引用就是這個意思。

注意: 引用類型 必須和引用 實體 同種類型 。也就是說在上面這個代碼里面,aa要和a是同一個類型(int)。

1.1 常引用

?int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}

在這個代碼里面,如果a是const int類型的,那就不可以對aa進行++的操作(會報錯)。

舉個例子,小明不可以吃飯,那也就是說明明不可以吃飯。

1.2 傳值返回與傳引用返回

以值作為參數或者返回值類型,在傳參和返回期間,函數不會直接傳遞實參或者將變量本身直
接返回,而是傳遞實參或者返回變量的一份臨時的拷貝,因此用值作為參數或者返回值類型,效
率是非常低下的,尤其是當參數或者返回值類型非常大時(比如說map<string,string>),效率就更低。
傳值返回:
int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

在這段代碼里面,最終的結果是2。但是他在return a的時候產生了一份臨時拷貝,然后把這個臨時拷貝賦值給了b。我們前面說的消耗就是在這里。

PS:之所以要拷貝的原因涉及到函數棧幀的創建與銷毀,簡單來說就是a出了這個Fanc就會自動銷毀,所以編譯器要通過產生臨時拷貝的方式來進行賦值。

傳引用返回:

?int& Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

在這段代碼里面,a其實是有危險的,因為是&,所以在這里并沒用產生a的臨時拷貝,也就是說在這里實際上造成了野指針現象。

修改的辦法有兩種。

一種是加一個全局變量

int c;//  全局變量int& Fanc(int a) {c = a + 1;  return c;   
}int main() {int b = 1;b = Fanc(b);cout << b << endl; return 0;
}

傳入的是全局變量(或者靜態變量也可以),所以在這里并不會被銷毀。

還有一種是通過引用傳遞參數

int& Fanc(int& a) {a++;        // 直接修改傳入的參數return a;   // 返回傳入參數的引用
}int main() {int b = 1;Fanc(b); cout << b << endl;  return 0;
}
通過引用傳遞參數,直接修改傳入的參數并返回其引用

1.3?傳值、傳引用

首先,傳值和傳引用與傳值返回與傳引用返回不是同一個東西。

傳值:

??int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

這個就是我們在一開始的學習中使用函數的方式。消耗也比較大。

傳引用:

?
?int Fanc(int& a)
{a++;return a;
}int main()
{int b=1;Fanc(b);//沒有了b=...cout<<b<<endl;return 0;
}?

直接修改傳入的參數,而不需要返回值。同時代價也小。

1.4?引用和指針的區別

在C++中,引用和指針都是用來間接訪問變量的機制,但它們之間有一些重要的區別:

1. 引用是變量的別名,而指針是一個獨立的實體。引用在聲明時必須初始化,并且一旦引用和原變量綁定后,就無法再綁定到其他變量(這一點很重要);而指針可以在聲明后指向不同的變量。

2. 引用不需要使用解引用操作符(*)來訪問其綁定的變量,而指針需要使用解引用操作符(*)來訪問其指向的變量。

3. 引用不能指向空值(null),而指針可以指向空值。

4. 指針可以進行算術運算,而引用不支持。

總的來說,引用更直觀和安全,因為它不需要對空值進行處理,而指針更靈活,因為它可以指向不同的對象和進行算術運算。在實際使用中,應根據具體情況選擇合適的機制。

2. 內聯函數

inline 修飾 的函數叫做內聯函數, 編譯時 C++ 編譯器會在 調用內聯函數的地方展開 ,沒有函數調
用建立棧幀的開銷,內聯函數提升程序運行的效率。
inline int add(int a, int b)
{return a + b;
}int main() 
{int result = add(3, 4);  // 編譯器可能會將 add 函數直接插入此處cout << "Result: " << result << endl;return 0;
}

內聯函數的本質就是替換,通過把main函數里面的add直接轉換成a+b,通過這樣的方式來提升效率。

2.1?內聯函數特性

inline 是一種 以空間換時間 的做法,如果編譯器將函數當成內聯函數處理,在 編譯階段,會
用函數體替換函數調用 ,缺陷:可能會使目標文件變大,優勢:少了調用開銷,提高程序運
行效率。
inline 對于編譯器而言只是一個建議,不同編譯器關于 inline 實現機制可能不同 ,一般建
議:將 函數規模較小 ( 即函數不是很長,具體沒有準確的說法,取決于編譯器內部實現 )
是遞歸、且頻繁調用 的函數采用 inline 修飾,否則編譯器會忽略 inline 特性(不然的話會造成代碼膨脹)。
PS: inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址
了,鏈接就會找不到。
內聯函數從某種意義上來說替代了宏(即宏函數)。

3. auto關鍵字

auto我從剛剛學到他的時候認為沒什么用,但是當我學到后面的時候,我才發現他是那么的好用,因為到后面很多時候類型是一層套一層,就是說會特別的長,這個時候auto的作用就體現出來了。

他的本質就是讓編譯器自動推導類型。換種說法就是把我們的這部分工作交給了編譯器。

3.1 auto使用時候的注意事項

使用 auto 定義變量時必須對其進行初始化,在編譯階段編譯器需要根據初始化表達式來推導 auto
的實際類型 。因此 auto 并非是一種 類型 的聲明,而是一個類型聲明時的 占位符 ,編譯器在編
譯期會將 auto 替換為變量實際的類型
int main()
{auto x = 10,y=3;return 0
}

上面這種就是合法的,因為auto在同一行只會進行一次推導,如果說y=3.3,那么編譯器就會報錯。

3.2 auto不能推導的類型

auto不可以作為函數的參數類型,比如說:

auto fanc(auto a)
{.......
}

這種是不合法的(其實沒有什么別的原因,就是設計者在設計的時候沒有允許這種用法,我們在后面會學到一種template<class T>的東西,他可以實現我們上面想要達到的目的)。

同時,auto也不可以作為數組的類型,簡單來說就是:

int main()
{auto arr[]={1,2,3,4,5,6}return 0;
}

這種也是不可以的(原因如上)。

4. 范圍for

對于一個 有范圍的集合 而言,由程序員來說明循環的范圍是多余的,有時候還會容易犯錯誤(如越界訪問)。因 此C++11 中引入了基于范圍的 for 循環。 for 循環后的括號由冒號 分為兩部分:第一部分是范 圍內用于迭代的變量,第二部分則表示被迭代的范圍
void TestFor()
{int arr[] = { 1, 2, 3, 4, 5 };for(auto& a : arr)a *= 2;
}

這就是范圍for的用法,通過這樣的方式就可以使arr里面的數都*上2。

PS:加上引用就可以改變arr,如果說是想要改變范圍for里面的數組,那最好就是在auto后面加一個&。

4.1 范圍for的原理

范圍for的底層就是迭代器(iterator),他在編譯器編譯的時候就會修改為迭代器。

所以說我們在里面想要遍歷或者修改的東西必須有beginend的方法,beginend就是for循環迭代的范圍。

5. 空指針nullptr

程序本意是想通過 f(NULL) 調用指針版本的 f(int*) 函數,但是由于 NULL 被定義成 0 ,因此與程序的
初衷相悖。 因此發明了nullptr,
PS: 在使用 nullptr 表示指針空值時,不需要包含頭文件。
因此我們在使用的時間候直接把他當做一個不能表示0的NULL去使用就好。

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

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

相關文章

注意力機制,本質上是在做什么?

本文以自注意機制為例&#xff0c;輸入一個4*4的矩陣 如下&#xff1a; input_datatorch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16] ],dtypetorch.float) 得到Q和K的轉置如下。 此時&#xff0c;計算QK^T ,得到如下結果 第一行第一個位置就是第一條樣本和第…

記一次wsl2+docker無法運行的經歷

前情提要 由于某個大創項目的需要和對貓娘機器人的迫切渴求&#xff08;bushi 需要在電腦里面安裝docker desktop。由于電腦里面安裝了wsl2環境 因此決定使用wsl2dockerdesktop的方式配置docker 遇到的問題 在像往常一樣安裝docker desktop并且啟動時 提示錯誤&#xff1a; …

PageHelper插件依賴引入不報錯,但用不了

情況: 父模塊pom. Xml 引入1. 4. 0以上版本的pagehelper-spring-boot-starter。 要用到插件的子模塊&#xff0c;去掉版本號&#xff0c;引入和父模塊一樣的依賴。 引入成功&#xff0c;沒有報錯&#xff0c;但是打開右邊的maven里面沒有找到PageHelper插件。 終端清空并重…

Windows搭建免翻墻的BatteryHistorian

文章參考 GitCode - 全球開發者的開源社區,開源代碼托管平臺 免翻墻的BatteryHistorian主要原理&#xff1a;修改go源碼 1.安裝Java環境 1.點擊下載 Java JDK&#xff0c;并安裝,一路next 2.java -version 檢驗是否安裝成功 2.安裝Git工具 1、點擊下載 Git&#xff0c;并…

項目中pnpm版本和全局pnpm版本不一致

項目中pnpm版本和全局pnpm版本不一致 檢查package.json中&#xff0c;是否存在"packageManager": “pnpm8.6.10”&#xff0c;限制了pnpm的版本。

透析Vue的nextTick原理

nextTick 是 Vue.js 中的一個核心機制&#xff0c;用于在 下一次 DOM 更新周期后 執行回調函數。它的核心原理是 利用 JavaScript 的事件循環機制&#xff08;Event Loop&#xff09;&#xff0c;結合微任務&#xff08;Microtask&#xff09;或宏任務&#xff08;Macrotask&am…

WRF/Chem 模式技術解讀:為大氣污染治理提供有力支撐

技術點目錄 第一部分、WRF-Chem模式應用案例和理論基礎第二部分、Linux環境配置及WRF-CHEM第三部分、WRF-Chem模式編譯&#xff0c;排放源制作第四部分、WRF-Chem數據準備&#xff08;氣象、排放、初邊界條件等&#xff09;&#xff0c;案例實踐第五部分、模擬結果提取、數據可…

ccfcsp2701如此編碼

//如此編碼 #include<iostream> using namespace std; int main(){int n,m;cin>>n>>m;int a[21],b[21],c[21];for(int i1;i<n;i){cin>>a[i];}c[0]1;for(int i1;i<n;i){c[i]c[i-1]*a[i];}b[1](m%c[1])/c[0];int s1,s20;for(int i2;i<n;i){s2s2…

74HC04(反相器)和74HC14(反相器、施密特觸發器)的區別

74HC04和74HC14的具體區別詳解 同樣具有反相器功能&#xff0c;你知道74HC04和74HC14的具體區別嗎&#xff1f; 74HC04 對于74HC04很好理解&#xff0c;輸入低電平&#xff0c;輸出高電平&#xff1b;輸入高電平&#xff0c;輸出低電平。 建議操作條件&#xff1a; 下圖是TI的…

如何緩解大語言模型推理中的“幻覺”(Hallucination)?

目錄 如何緩解大語言模型推理中的“幻覺”&#xff08;Hallucination&#xff09;&#xff1f; 1. 什么是大語言模型的“幻覺”&#xff08;Hallucination&#xff09;&#xff1f; 幻覺的常見類型 2. 如何緩解大模型的幻覺問題&#xff1f; 方法 1&#xff1a;使用知識檢索…

Linux權限管理詳解

Linux權限管理系統 Linux作為一個多用戶操作系統&#xff0c;其權限管理系統是保障系統安全的重要組成部分。通過合理設置文件和目錄的權限&#xff0c;可以有效控制用戶對系統資源的訪問。 一、基本權限概念 Linux系統中的權限分為三類&#xff1a; 讀權限(r)&#xff1a;…

第十四次CCF-CSP認證(含C++源碼)

第十四次CCF-CSP認證 賣菜滿分思路 買菜滿分思路 再賣菜滿分題解&#xff08;差分約束&#xff09;solution 1(枚舉 correct but 超時)solution 2(正解) 賣菜 題目鏈接 滿分思路 就是模擬一下這個調整第二天菜價的過程&#xff0c;其中對于兩種只有一個鄰居的情況下做出調整&…

CCBCISCN復盤

AWDP – ccfrum 自己搭了一下環境, 復現一下這道題目, 之前比賽的時候完全沒想到這個漏洞要怎么打, 修也不知道要怎么修, 就僅僅是對用戶名的賬號和密碼進行了一下過濾, 完全沒起到作用, 唉, 實在太菜 如果想要嘗試復現的話可以嘗試拉取這個鏡像, 我打完之后就直接把這個容器給…

(每日一道算法題)交易逆序對的總數

LCR 170. 交易逆序對的總數 - 力扣&#xff08;LeetCode&#xff09; 在股票交易中&#xff0c;如果前一天的股價高于后一天的股價&#xff0c;則可以認為存在一個「交易逆序對」。請設計一個程序&#xff0c;輸入一段時間內的股票交易記錄 record&#xff0c;返回其中存在的「…

【操作系統】共享數據的競爭問題

共享數據的競爭問題 問題&#xff1a;保護中斷與主程序共享的avg_data方法一&#xff1a;使用關中斷保護1. 添加關中斷宏2. 修改數據讀取代碼3. 修改中斷服務程序&#xff08;ISR&#xff09; 方法二&#xff1a;使用原子操作&#xff08;需平臺支持&#xff09;1. 定義原子類型…

VS010生成可由MATLAB2016調用的DLL文件方法

親測實用&#xff0c;不用配置雜七雜八的依賴項 1&#xff1a;新建Win32的DLL輸出項目 2&#xff1a;修改為release模式 3&#xff1a;添加calc.cpp文件&#xff0c;即要導出的函數myadd&#xff1a; #include "calc.h" __declspec(dllexport) int myadd(int a,in…

機器學習Pandas_learn4

import pandas as pddef calculate_goods_covariance():# 定義商品銷售數據字典goods_sales_data {"時期": ["一期", "二期", "三期", "四期"],"蘋果": [15, 16, 3, 2],"橘子": [12, 14, 16, 18],&quo…

優選算法系列(3.二分查找 )

目錄 一.二分查找&#xff08;easy&#xff09; 題目鏈接&#xff1a;704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 代碼&#xff1a; 二.在排序數組中查找元素的第?個和最后?個位置&#xff08;medium&#xff09; 題目鏈接&#xff1a;34.…

DAY36貪心算法Ⅴ

56. 合并區間 - 力扣&#xff08;LeetCode&#xff09; class Solution { static bool cmp(vector<int>&a,vector<int>&b){return a[0] < b[0]; } public:vector<vector<int>> merge(vector<vector<int>>& intervals) {so…

阿里云服務器部署 五 Nginx + springboot

Nginx的部分配置 1. 基礎容災配置&#xff08;被動健康檢查&#xff09; 在 upstream 塊中&#xff0c;通過 max_fails 和 fail_timeout 參數定義故障轉移規則&#xff1a; 在 upstream 塊中&#xff0c;通過 max_fails 和 fail_timeout 參數定義故障轉移規則&#xff1a;…