【C++干貨基地】揭秘C++11常用特性:內聯函數 | 范圍for | auto自動識別 | nullptr指針空值


在這里插入圖片描述

🎬 鴿芷咕:個人主頁

?🔥 個人專欄: 《C++干貨基地》《粉絲福利》

??生活的理想,就是為了理想的生活!

引入

??哈嘍各位鐵汁們好啊,我是博主鴿芷咕《C++干貨基地》是由我的襄陽家鄉零食基地有感而發,不知道各位的城市有沒有這種實惠又全面的零食基地呢?C++ 本身作為一門篇底層的一種語言,世面的免費課程大多都沒有教明白。所以本篇專欄的內容全是干貨讓大家從底層了解C++,把更多的知識由抽象到簡單通俗易懂。

?? 推薦

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到網站。

文章目錄

  • 引入
  • ?? 推薦
  • 一、內聯函數
    • 1.1 內聯函數的概念
    • 1.2 內聯函數的特性
      • 內聯函數適合每個函數都用嗎?
      • 內聯函數需要聲明和定義分離嗎?
  • 二、auto關鍵字
    • 2.1 auto 的使用場景
    • 2.2 auto 不能推導的場景
  • 三、基于范圍for循環
    • 3.1 范圍for的語法
    • 3.2 范圍for 的注意事項
  • 四、指針空值 nullptr
    • 4.1 C++98中的指針空值
    • 4.2 nullptr的由來
  • 📝文章結語:

一、內聯函數

1.1 內聯函數的概念

以往我們在C語言中實現比較簡單的函數來說都是用宏來實現的,比如說實現一個加法,但是用宏實現的小型函數有很多缺點:

  • 第一點就是宏經常容易寫錯,末尾的引號問題和運算符優先級問題等等
  • 第二點就是宏他并沒有類型安全檢查就算是一個加法也有可能有人給你傳倆個字符
  • 第三點就是宏不方便調試,導致代碼可讀性差

所以在C++中就采用了內聯函數和枚舉來解決宏的使用的問題

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

1.2 內聯函數的特性

內聯函數是以inline修飾的函數,在調用其該函數的時候會直接在調用處展開并不會開辟函數的棧幀空間所以非常適用在一下短小函數上面:

下面就給大家來看一下使用內聯函數的效果:

🍸 代碼一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;int Add(int x, int y)
{int ret = x + y;return ret;
}int main()
{int ret = Add(1,2);return 0;
}

在這里插入圖片描述

🍸 代碼二:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;inline int Add(int x, int y)
{int ret = x + y;return ret;
}int main()
{int ret = Add(1,2);return 0;
}

在這里插入圖片描述
這里我們就可以看到只要函數我們加了 inline 關鍵字在調用的時候就直接展開不會開辟新的棧幀空間然后去 call 調用它。

內聯函數適合每個函數都用嗎?

內聯函數看起來不用開辟函數的棧幀空間大大結束了效率但是每個短小的函數都適合使用內聯函數嗎?

  • 其實函數在調用次數過多的情況下就不適合使用內聯函數,這樣就會導致代碼膨脹到處都是重復的代碼,從而使得可執行程序變大;
  • 還有在函數的遞歸時也不能使用內聯函數,函數棧幀是可以復用的,但內聯函數一旦使用也會導致代碼膨脹

🔥 注: inline對于編譯器而言只是一個建議,不同編譯器關于inline實現機制可能不同,一般建
議:將函數規模較小(即函數不是很長,具體沒有準確的說法,取決于編譯器內部實現)、不
是遞歸、且頻繁調用的函數采用inline修飾,否則編譯器會忽略inline特性。下圖為
《C++prime》第五版關于inline的建議:

在這里插入圖片描述

內聯函數需要聲明和定義分離嗎?

inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址
了,鏈接就會找不到。

在這里插入圖片描述

二、auto關鍵字

auto 關鍵字聽聽名字就非常簡單,是C++11的時候,標準委員會賦予了auto全新的含義即可以自動推導變量類型使用起來也十分簡單:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;int main()
{int a = 10;auto p1 = a;auto* p2 = &a;auto& p3 = a;return 0;
}

這里auto后面加的 * 號就代表指針,&和以前一樣是引用是我們指定自動類型。

🔥 注:使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據初始化表達式來推導auto的實際類型。
因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編譯期會將auto替換為變量實際的類型。

2.1 auto 的使用場景

auto 關鍵的意義其實并不是像我們前面那樣去使用,是針對特別復雜的類型配合使用的比如:

🍸 場景一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;int fun(int x, int y)
{int ret = x + y;return ret;
}
int main()
{int(*fp1)(int, int) = fun;auto fp2 = fun;return 0;
}

🍸 場景一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<map>
#include<string>
using namespace std;int main()
{std::map<std::string, std::string> dict;std::map<std::string, std::string>::iterator it = dict.begin();auto it = dict.begin();return 0;
}

2.2 auto 不能推導的場景

  • auto不能作為函數的參數
// 此處代碼編譯失敗,auto不能作為形參類型,因為編譯器無法對a的實際類型進行推導
void TestAuto(auto a)
{}
  • auto不能直接用來聲明數組
void TestAuto()
{int a[] = {1,2,3};auto b[] = {456};
}

三、基于范圍for循環

在以前只要遍歷數組我們就可能想到,使用for循環來遍歷數組比如這樣:

void TestFor()
{
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++11 中新增加了范圍 for 的概念

3.1 范圍for的語法

for循環后的括號由冒號“ :”分為兩部分:

  • 第一部分是范圍內用于迭代的變量
  • 第二部分則表示被迭代的范圍。
void TestFor()
{int array[] = { 1, 2, 3, 4, 5 };for(auto& e : array)e *= 2;for(auto e : array)cout << e << " ";
}

在這里就巧妙的運用了我們上面講的 auto 關鍵字來自動識別數組元素的類型:

  • e 在這里是數組元素的臨時拷貝所以我們如果想要改變數組元素
  • 就得指定自動類型為引用,去用于改變數組元素

3.2 范圍for 的注意事項

🔥 for循環迭代的范圍必須是確定的

  • 對于數組而言,就是數組中第一個元素和最后一個元素的范圍;
  • 對于類而言,應該提供begin和end的方法,begin和end就是for循環迭代的范圍。

例如以下代碼就是錯誤的:

  • 這里我們并不明確因為for的范圍不確定
void TestFor(int array[])
{for(auto& e : array)cout<< e <<endl;
}

四、指針空值 nullptr

4.1 C++98中的指針空值

一般我們定義變量好的習慣是每一個變量都初始化值但是 C++98 中 祖師爺在定義 NULL 指針空值的時候是這樣定義的:

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

這就導致了一個問題大家看一下下面這個代碼結果你們猜是什么呢?

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;
}

在這里插入圖片描述

誒這里使用指針 NULL 定義空值的時候就出現問題了,所以在C++11中新增了一個關鍵字來填這個缺陷

4.2 nullptr的由來

nullptr 的由來就是因為祖師爺在一開始定義 NULL是使用宏定義這就導致

  • NULL 被替換成 0 了,而不是((void *)0);
  • 所以新增了一個關鍵字 nullptr == ((void *)0);

注意:

  1. 在使用nullptr表示指針空值時,不需要包含頭文件,因為nullptr是C++11作為新關鍵字引入的。

  2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節數相同。

  3. 為了提高代碼的健壯性,在后續表示指針空值時建議最好使用nullptr。

📝文章結語:

?? 看到這里了還不給博主扣個:
?? 點贊🍹收藏 ?? 關注
💛 💙 💜 ?? 💚💓 💗 💕 💞 💘 💖
拜托拜托這個真的很重要!
你們的點贊就是博主更新最大的動力!

在這里插入圖片描述

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

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

相關文章

平臺工程: 用Backstage構建開發者門戶 - 2

本文介紹了如何使用開源Backstage構建自己的開發者門戶&#xff0c;并基于此實踐平臺工程。本系列共兩篇文章&#xff0c;這是第二篇。原文: Platform Engineering: Building Your Developer Portal with Backstage — Part 2 在本教程第一部分中我們了解了Backstage這個用于構…

外貿網站模板建站

測繪檢測wordpress外貿主題 簡潔實用的wordpress外貿主題&#xff0c;適合做測繪檢測儀器設備的外貿公司使用。 https://www.jianzhanpress.com/?p5337 白馬非馬衣服WordPress外貿建站模板 白馬非馬服裝行業wordpress外貿建站模板&#xff0c;適用于時間服裝企業的官方網站…

Git 如何上傳本地的所有分支

Git 如何上傳本地的所有分支 比如一個本地 git 倉庫里定義了兩個遠程分支&#xff0c;一個名為 origin&#xff0c; 一個名為 web 現在本地有一些分支是 web 遠程倉庫沒有的分支&#xff0c;如何將本地所有分支都推送到 web 這個遠程倉庫上呢 git push web --all

pytorch loss函數整理

變量名解釋 logits&#xff1a;未經過normalize&#xff08;未經過激活函數處理&#xff09;的原始分數&#xff0c;例如一個mlp將特征映射到num_target_class維的輸出tensor就是logits。 probs&#xff1a;probabilities的簡寫&#xff0c;logits經過sigmoid函數&#xff0c;…

Doris實戰——銀聯商務實時數倉構建

目錄 前言 一、應用場景 二、OLAP選型 三、實時數倉構建 四、實時數倉體系的建設與實踐 4.1 數倉分層的合理規劃 4.2 分桶分區策略的合理設置 4.3 多源數據遷移方案 4.4 全量與增量數據的同步 4.5 離線數據加工任務遷移 五、金融級數倉穩定性最佳實踐 5.1 多租戶資…

Jenkins的Pipeline概念

文章目錄 Pipeline什么是Jenkins Pipeline聲明式和腳本式Pipeline語法為何使用PipelinePipeline概念PipelineNodeStageStep Pipeline語法概述聲明式Pipeline腳本式Pipeline Pipeline示例 參考 Pipeline 什么是Jenkins Pipeline Jenkins Pipeline是一套插件&#xff0c;它支持…

【Django】model模型—模型繼承

Django中三種繼承風格 抽象基類&#xff1a;僅將父類用于子類公共信息的載體&#xff0c;這樣的父類永遠都不會單獨使用。多表繼承&#xff1a;繼承了一個模型&#xff08;可能來源其它應用&#xff09;&#xff0c;且想要每個模型都有對應的數據表。代理模型&#xff1a;只想…

JProfiler相關問題及答案(2024)

1、JProfiler是什么及其用途 JProfiler是一款功能豐富的商業Java性能剖析&#xff08;profiling&#xff09;工具&#xff0c;它主要面向開發者和性能分析師&#xff0c;用于監測和分析Java應用程序的運行時行為。以下是對JProfiler的一些詳細介紹和它的主要用途&#xff1a; …

webpack的一些知識

核心 webpack 是用來搭建前端工程的它運行在node環境中&#xff0c;它所做的事情&#xff0c;簡單來說&#xff0c;就是打包具體來說&#xff0c;就是以某個模塊作為入口&#xff0c;根據入口分析出所有模塊的依賴關系&#xff0c;然后對各種模塊進行合并、壓縮&#xff0c;形…

洛谷P1157 組合的輸出

深搜板子加一點點修改&#xff0c;適合初學者體會深搜&#xff0c;具體看代碼 題目鏈接 ACcode #include<bits/stdc.h>using namespace std;int a, b;bitset<50>vis;//剪枝 int d[50];void dfs(int x) {if (x b 1) {for (int i 1;i < b;i)cout << se…

HBM(High Bandwidth Memory)

選擇正確的高帶寬內存 構建高性能芯片的選擇越來越多&#xff0c;但附加內存的選擇卻幾乎沒有變化。為了在汽車、消費和超大規模計算中實現最大性能&#xff0c;選擇取決于一種或多種 DRAM&#xff0c;而最大的權衡是成本與速度。 盡管多年來人們一直在努力用更快、更便宜或更…

Linux:kubernetes(k8s)搭建mater節點(kubeadm,kubectl,kubelet)(2)

安裝k8有多種方式如&#xff1a; minikube kubeadm 二進制安裝 命令行工具 我這里就使用kubeadm進行安裝 環境 3臺centos7 master ip &#xff1a;192.168.113.120 2G運存 2內核 node1 ip &#xff1a;192.168.113.121 2G運存 2內核 node2 ip &#xff1a;192.168.1…

重構與設計模型的完美融合:構建穩定可擴展系統的關鍵步驟

在軟件開發的漫長旅程中&#xff0c;系統的穩定性和可擴展性一直是開發者們追求的目標。為了實現這一目標&#xff0c;重構和設計模型成為了不可或缺的兩個關鍵元素。本文將探討如何通過重構&#xff0c;使系統更穩定、更具可擴展性&#xff0c;并深入研究如何將重構與設計模型…

JavaEE:多線程(3):案例代碼

目錄 案例一&#xff1a;單例模式 餓漢模式 懶漢模式 思考&#xff1a;懶漢模式是否線程安全&#xff1f; 案例二&#xff1a;阻塞隊列 可以實現生產者消費者模型 削峰填谷 接下來我們自己實現一個阻塞隊列 1.先實現一個循環隊列 2. 引入鎖&#xff0c;實現線程安全 …

運用qsort函數進行快排并使用C語言模擬qsort

qsort 函數的使用 首先qsort函數是使用快速排序算法來進行排序的&#xff0c;下面我們打開官網來查看qsort是如何使用的。 這里有四個參數&#xff0c;首先base 是至待排序的數組的首元素的地址&#xff0c;num 是值這個數組的元素個數&#xff0c;size 是指每個元素的大小&am…

Python猜數字小游戲

下面這段代碼是一個簡單的數字猜測游戲&#xff0c;其中計算機已經提前計算出了414 // 23的結果并存儲在變量num中。然后&#xff0c;程序會提示用戶來猜測這個結果。 以下是代碼的主要步驟和功能&#xff1a; 初始化&#xff1a; num 414 // 23&#xff1a;計算414除以23的整…

Linux:各目錄含義

簡介 學習Linux各目錄含義之前&#xff0c;我們首先要了解一下Filesystem Hierarchy Standard&#xff08;文件系統層次結構標準&#xff09;。 FHS FHS&#xff0c;即文件系統層次結構標準&#xff08;Filesystem Hierarchy Standard&#xff09;&#xff0c;是Linux和類Un…

深入了解Redis:配置文件、動態修改和安全設置

Redis 是一個開源的內存中數據結構存儲系統&#xff0c;它可以用作數據庫、緩存和消息中間件。在使用 Redis 時&#xff0c;了解其配置選項是至關重要的。本文將詳細介紹 Redis 的配置文件和常用配置項&#xff0c;并提供一些示例來說明如何設置和修改這些配置。 Redis 配置文…

基于stm32F103的座面聲控臺燈

1.基本內容&#xff1a; 設計一個放置在桌面使用的臺燈&#xff0c;使用220v交流電供電。具備顯示屏能夠實時顯示日期&#xff08;年、月、日和星期&#xff09;&#xff0c;時間&#xff08;小時、分鐘、秒&#xff09;和溫度&#xff08;攝氏度&#xff09;&#xff1b;能夠通…

Python爬取天氣數據及可視化分析!(含源碼)

天氣預報我們每天都會關注&#xff0c;我們可以根據未來的天氣增減衣物、安排出行&#xff0c;每天的氣溫、風速風向、相對濕度、空氣質量等成為關注的焦點。本次使用python中requests和BeautifulSoup庫對中國天氣網當天和未來14天的數據進行爬取&#xff0c;保存為csv文件&…