4. C++入門:內聯函數、auto關鍵字、范圍for及nullptr

內聯函數

概念

以inline修飾的函數叫做內聯函數,編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數調用建立棧幀的開銷,內聯函數提升程序運行的效率

對比C的宏

C語言不足:宏

#define ADD(x, y) ((x)+(y))int main()
{int ret1 = ADD(2, 3);  //((2)+(3))*5int a = 1, b = 2;int ret2 = ADD(a | b, a & b);  //((a | b)+(a & b))return 0;
}

宏的缺點:

  1. 容易出錯,語法細節多
  2. 不能調試
  3. 沒有類型安全的檢查
inline int Add(int x, int y)
{int c = x + y;return c;
}int main()
{int ret1 = Add(1, 2);int ret2 = ADD(1, 2);return 0;
}

用enum,const,inline替代宏
enum,const替代的是宏常量
inline替代宏函數

普通函數要建立棧幀,會有很多的消耗

內聯函數的特點:

  1. 不用建立棧幀,會在調用的地方展開,沒有函數調用棧幀的開銷,提高了效率
  2. 克服了宏的缺點
  3. 可以調試
  4. 好寫,語法簡單
查看方式

Debug版本下
![[Pasted image 20240515101325.png]]

內聯函數在默認情況下,沒有去展開
![[Pasted image 20240515101839.png]]

在項目屬性里將常規里的調試信息格式改為程序數據庫
![[Pasted image 20240515101906.png]]

優化里的內聯函數擴展改為只適用于_inline(/Ob1)
再進行調試
![[Pasted image 20240515102038.png]]

這是沒有call了,不會建立棧幀

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

內聯只適合于頻繁調用的小函數,小于等于10行代碼

指令影響編譯好的可執行程序的大小
如果暴力地對100行的大函數內聯展開
比如有10000個調用這個函數的地方
展開合計:100*10000行指令
如果展開,不需要call,有多少個調用的地方就展開多少次,假設調用的地方是1行指令,展開成100行指令
不展開合計:100+10000行指令
有10000個調用的地方,不展開,每次調用只有一行指令

內聯函數聲明定義分離
#pragma once
#include <iostream>
using namespace std;inline void f(int i);
#include "Func.h"void f(int i)
{cout << i << endl;
}
#include "Func.h"int main()
{f(10);return 0;
}

內聯函數不能聲明和定義分離
如果分離在兩個文件,會報錯,發生鏈接錯誤
在編譯的時候,發現函數和參數能匹配上,先過

#pragma once
#include <iostream>
using namespace std;inline void f(int i);
void func();
#include "Func.h"void f(int i)
{cout << i << endl;
}void func()
{f(5);
}
#include "Func.h"int main()
{//f(10);func();return 0;
}

調f不可以,調func可以
不可以直接調,可以間接調

調用f的時候需要找f的地址,因為編譯的時候只有聲明
鏈接的時候沒有找到內聯函數的地址
因為內聯函數不會生成地址,或者生成的地址不會生成符號表
內聯函數直接再調用的地方展開了,就不需要地址
所以會報錯

在Test.cpp自己的文件里調的時候,不會到鏈接那一步去找
因為直接有聲明和定義,在Func.cpp里面,直接拿定義就在這展開了

內聯函數如果分離在.h和.cpp,就不能再其他文件去用
如果再其他文件去用會報錯
只能在當前這個cpp文件里使用

內聯函數最好不要聲明和定義分離
這樣不管在哪個文件都可以使用,聲明和定義在同一個文件就不需要鏈接了,因為直接就能找到定義

auto關鍵字

隨著程序越來越復雜,程序中用到的類型也越來越復雜,經常體現在:

  1. 類型難于拼寫
  2. 含義不明確導致容易出錯

是可以通過typedef給類型取別名
但是在編程時,常常需要把表達式的值賦值給變量,這就要求在聲明變量的時候清楚地知道表達式的類型。然而有時候要做到這點并非那么容易,因此C++11給auto賦予了新的含義

auto簡介

可以自己推導類型

int main()
{int a = 0;int b = a;auto c = a;auto d = &a;auto* e = &a;auto& f = a;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;cout << typeid(e).name() << endl;cout << typeid(f).name() << endl;return 0;
}

這里c就是int類型
typeid可以用來打印一個對象的類型
![[Pasted image 20240515132627.png|166]]

可以省略下面的類型的定義,使代碼短一點點

#include <vector>
#include <string>int main()
{vector<string> v;//vector<string>::iterator it = v.begin();auto it = v.begin();return 0;
}
注意
  1. 使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據初始化表達式來推導auto的實際類型。因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編譯期會將auto替換為變量實際的類型。
  2. auto與指針和引用結合起來使用
    用auto聲明指針類型時,用auto和auto*沒有任何區別,但用auto聲明引用類型時則必須加&
  3. 在同一行定義多個變量
    當在同一行聲明多個變量時,這些變量必須是相同的類型,否則編譯器將會報錯,因為編譯器實際只對第一個類型進行推導,然后用推導出來的類型定義其他變量。
  4. auto不能作參數,返回值也不支持
  5. auto的意義就是,定義對象時,類型較長,用它比較方便
  6. auto不能聲明數組

范圍for

對于一個有范圍的集合而言,由程序員來說明循環的范圍是多余的,有時候還會容易犯錯誤。因此C++11中引入了基于范圍的for循環。for循環后的括號由冒號“ :”分為兩部分:第一部分是范圍內用于迭代的變量,第二部分則表示被迭代的范圍

int main()
{int array[] = {1, 2, 3, 4, 5};for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)array[i] *= 2;for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)cout << *p << endl;
}

對數組進行遍歷,C語言進行遍歷,使用下標計算數組的大小,或者搞一個數組的指針去算,比較麻煩

int main()
{int array[] = {1, 2, 3, 4, 5};for (auto e : array){cout << e << " ";}cout << endl;return 0;
}

![[Pasted image 20240522092615.png]]

會依次取數組中的值賦值給e
自動判斷結束,自動++往后遍歷
這里的auto雖然也可以輸入實際的類型,但是用了auto,就算后面數組對象的類型變了,這里也不需要修改代碼
注意:與普通循環類似,可以用continue來結束本次循環,也可以用break來跳出整個循環

int main()
{int array[] = {1, 2, 3, 4, 5};for (auto e : array){e++;cout << e << " ";}cout << endl;for (auto e : array){cout << e << " ";}cout << endl;return 0;
}

如果想對每個數據++一下
![[Pasted image 20240522093833.png]]

發現并沒有真正++。
只是修改了e,沒有修改了數組中的數值。
因為是依次取數組中的每個值賦值給e,e的改變不會影響數組里面。
要修改的話,要加個引用

int main()
{int array[] = {1, 2, 3, 4, 5};for (auto& e : array){e++;cout << e << " ";}cout << endl;for (auto e : array){cout << e << " ";}cout << endl;return 0;
}

![[Pasted image 20240522094114.png]]

使用條件
  1. for循環迭代的范圍必須是確定的
    對于數組而言,就是數組中第一個元素和最后一個元素的范圍;對于類而言,應該提供begin和end的方法,begin和end就是for循環迭代的范圍。
  2. 迭代的對象要實現++和==的操作。

指針空值nullptr

void f(int)  
{  cout<<"f(int)"<<endl;  
}  
void f(int*)  
{  cout<<"f(int*)"<<endl;  
}  int main()  
{  f(0);  f(NULL);  f((int*)NULL);return 0;  
}

函數參數只寫形參的類型,沒有寫形參的變量
不會報錯,實參傳給形參,形參可以不要,不要的時候可以作形參的匹配
![[Pasted image 20240522103025.png]]

第一個調用的是int,第二個NULL也調用的是int
因為C++的庫,在實現的時候NULL定義成了一個宏
NULL可能被定義為字面常量0,或者被定義為無類型指針(void*)的常量

#ifndef NULL  
#ifdef __cplusplus  
#define NULL 0  
#else  
#define NULL ((void *)0)  
#endif  
#endif

C++98中,字面常量0既可以是一個整形數字,也可以是無類型的指針(void*)常量,但是編譯器默認情況下將其看成是一個整形常量,如果要將其按照指針方式來使用,必須對其進行強轉(void*)0

注意
  1. 在使用nullptr表示指針空值時,不需要包含頭文件,因為nullptr是C++11作為新關鍵字引入的。
  2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節數相同。
  3. 為了提高代碼的健壯性,在后續表示指針空值時建議最好使用nullptr。

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

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

相關文章

python實現520表白圖案

今天是520哦&#xff0c;作為程序員有必要通過自己的專業知識來向你的愛人表達下你的愛意。那么python中怎么實現繪制520表白圖案呢&#xff1f;這里給出方法&#xff1a; 1、使用圖形庫&#xff08;如turtle&#xff09; 使用turtle模塊&#xff0c;你可以繪制各種形狀和圖案…

Docker 安裝kingbase V8r6

下載 官網下載&#xff0c;注意&#xff1a;這里下載 Docker 版本v8r6 安裝 # 導入鏡像 docker load -i kingbase.tar# 重命名 docker tag [image-name]:[tag] [new-image-name]:[new-tag]# 刪除 docker rmi [image-name]:[tag]# 創建容器 docker run -tid \ --privileged \…

python實現繪制煙花代碼

在Python中&#xff0c;我們可以使用多個庫來繪制煙花效果&#xff0c;例如turtle庫用于簡單的繪圖&#xff0c;或者更復雜的庫如pygame或matplotlib結合動畫。但是&#xff0c;由于turtle庫是Python自帶的&#xff0c;我們可以使用它來繪制一個簡單的煙花效果。 下面是一個使…

Stable Diffusion AMD加速方法-ZLUDA重出江湖

目前幾大開源的Stable Diffusion平臺&#xff0c;更新速度都慢了&#xff0c;一個是沒有太多新技術出現&#xff0c;新出的基礎模型也都不完整開源了&#xff08;API調用&#xff09;&#xff0c;能整的功能&#xff0c;也都整得差不多了。然后一群AMD死忠還在等著有一個能有一…

【前端】使用 Canvas 實現貪吃蛇小游戲

使用 Canvas 實現貪吃蛇小游戲 在這篇博客中&#xff0c;我們將介紹如何使用 HTML5 Canvas 和 JavaScript 實現一個簡單的貪吃蛇&#xff08;Snake&#xff09;小游戲。這個項目是一個基礎的游戲開發練習&#xff0c;它可以幫助你理解如何在 Canvas 上繪圖、如何處理用戶輸入以…

Laravel(Lumen8) + Supervisor 實現多進程redis消息隊列

相關文章:Supervisor守護進程工具安裝與使用 1、通用消息隊列 /App/Job/CommonJob.php: <?phpnamespace App\Jobs; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str;class CommonJob extends Job {public $timeout; //超時時間protected $data; //隊列…

Android:OkHttp網絡請求框架的使用

目錄 一&#xff0c;OkHttp簡介 二&#xff0c;OkHttp請求處理流程 三&#xff0c;OkHttp環境配置 四&#xff0c;OkHttp的使用 1.get網絡請求 2.post上傳表單數據 3.post上傳json格式數據 4.文件上傳 5.文件下載 一&#xff0c;OkHttp簡介 OkHttp是square公司推出的一…

npm 源管理工具 nrm

npm 源管理工具 nrm 安裝(可能很慢, 多試幾次) npm install -g nrm查看可選擇源列表 nrm ls切換源 nrm use <registry>如: nrm use taobao

rust的版本問題,安裝問題,下載問題

rust的版本、安裝、下載問題 rust版本問題&#xff0c; 在使用rust的時候&#xff0c;應用rust的包&#xff0c;有時候包的使用和rust版本有關系。 error: failed to run custom build command for pear_codegen v0.1.2 Caused by: process didnt exit successfully: D:\rus…

鴻蒙全面開發指南:入門、生態安全與資源支持

鴻蒙全面開發指南&#xff1a;入門、生態安全與資源支持 本文全面梳理了鴻蒙操作系統的開發入門流程&#xff0c;涵蓋了開發環境準備、工具使用、項目創建、模擬器配置到應用安全設計的各個方面。通過本文&#xff0c;讀者不僅能夠了解鴻蒙開發的基本步驟&#xff0c;也能深入理…

Aspose.PDF功能演示:在 JavaScript 中將 TXT 轉換為 PDF

您是否正在尋找一種在 JavaScript 項目中將純文本文件從TXT無縫轉換為PDF格式的方法&#xff1f;您來對地方了&#xff01;無論您是要構建 Web 應用程序、創建生產力工具&#xff0c;還是只是希望簡化工作流程&#xff0c;直接從 JavaScript 代碼中將 TXT 轉換為 PDF 的功能都可…

第3天 Web源碼拓展_小迪網絡安全筆記

1.關于web源碼目錄結構 #數據庫配置文件 后臺目錄 模板目錄 數據庫目錄 1.1數據庫配置文件: 1.1就拿wordpress來說,先到官網下載源碼:Download – WordPress.org,解壓源碼之后: 2.2找到目錄下名為 wp-config-sample.php的文件,這就是數據庫配置文件: 設想: 我們在滲透…

FOURIER NEURAL OPERATOR FOR PARAMETRIC PARTIAL DIFFERENTIAL EQUATIONS

參數偏微分方程的傅里葉神經算子 論文鏈接&#xff1a;https://arxiv.org/abs/2010.08895 項目鏈接&#xff1a;https://github.com/neuraloperator/neuraloperator 作者博客&#xff1a;https://zongyi-li.github.io/blog/2020/fourier-pde/ 參數偏微分方程的傅里葉神經算子…

本地部署Terraria泰拉瑞亞私服并通過內網穿透生成公網地址遠程聯機

文章目錄 前言1. 下載Terraria私服2. 本地運行Terraria 私服3. 本地Terraria私服連接4. Windwos安裝Cpolar 工具5. 配置Terraria遠程聯機地址6. Terraria私服遠程聯機7. 固定遠程聯機地址8. 固定的聯機地址測試 前言 本文將為你詳細介紹在本地如何運行泰拉瑞亞本地私服和結合C…

認識 React Hooks

回顧函數組件 函數組件 沒有組件實例 不能監聽各個生命周期 無法擴展屬性和方法 沒有 state 和 setState 只是輸入 props &#xff0c;輸出 jsx &#xff0c;純函數。 // class 組件class List extends React.Component {constructor(props) {super(props)}render() {con…

信息泄露--注意點點

目錄 明確目標: 信息泄露: 版本軟件 敏感文件 配置錯誤 url基于文件: url基于路由: 狀態碼: http頭信息泄露 報錯信息泄露 頁面信息泄露 robots.txt敏感信息泄露 .get文件泄露 --判斷: 搜索引擎收錄泄露 BP: 爆破: 明確目標: 失能 讀取 寫入 執行 信息泄…

【文末附gpt升級方案】Ilya離開OpenAI內幕探究:算力削減與商業優先策略的沖突

Ilya離開OpenAI內幕探究&#xff1a;算力削減與商業優先策略的沖突 一、引言 在人工智能&#xff08;AI&#xff09;領域的飛速發展中&#xff0c;OpenAI一直以其領先的技術和創新產品而備受矚目。然而&#xff0c;近日發生的Ilya Sutskever離開OpenAI的事件卻引起了業界的廣…

java企業級云MES系統全套源碼,支持app、小程序、H5、臺后管理

企業級云MES全套源碼&#xff0c;支持app、小程序、H5、臺后管理端 企業級智能制造MES系統源碼&#xff0c;技術架構&#xff1a;springboot vue-element-plus-admin MES指的是制造企業生產過程執行系統&#xff0c;是一套面向制造企業車間執行層的生產信息化管理系統。MES可以…

棧(基于動態順序表實現的棧)

棧的簡單介紹 關于棧的性質咳咳 棧&#xff1a;棧是一種特殊的線性表,其中只讓在一端插入和刪除元素。 后進先出 進行插入刪除的那一端叫棧頂&#xff0c;另一端叫棧底 我們實現的棧是基于一個動態順序表的的棧&#xff0c;會實現棧的 入棧&#xff0c;出棧&#xff0c;獲取…

修改默認時區,默認語言,默認國家

確認時區&#xff0c;語言&#xff0c;國家 build/make/target/product/languages_default.mkframeworks/base/packages/SettingsLib/res/xml/timezones.xml設備mk中添加相關內容 PRODUCT_PROPERTY_OVERRIDES \persist.sys.timezoneEurope/AmsterdamPRODUCT_PROPERTY_OVERRI…