網(wǎng)站直播間怎么做2023年9月疫情又開始了嗎
文章目錄
- 1.內(nèi)聯(lián)函數(shù)
- 2.auto關(guān)鍵字
- 2.1auto簡介
- 2.2auto的注意事項
- 2.3auto不能推導(dǎo)的場景
- 3.基于范圍的for循環(huán)(C++11)
- 4.指針空值nullptr(C++11)

1.內(nèi)聯(lián)函數(shù)
- 概念:
以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時C++編譯器會在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)調(diào)用建立棧幀的開銷,內(nèi)聯(lián)函數(shù)提升程序運行的效率。
下面的代碼就是不使用內(nèi)聯(lián)函數(shù),會建立棧幀。
如果在上述函數(shù)前增加inline關(guān)鍵字將其改成內(nèi)聯(lián)函數(shù),在編譯期間編譯器會用函數(shù)體替換函數(shù)的調(diào)用。
注意:Debug下,默認(rèn)是不展開的,因為展開以后不方便調(diào)試。需要設(shè)置編譯器。
此時,匯編代碼中是沒有call指令的,函數(shù)展開了。
- 特性
- inline是一種以空間換時間的做法,如果編譯器將函數(shù)當(dāng)成內(nèi)聯(lián)函數(shù)處理,在編譯階段,會用函數(shù)體替換函數(shù)調(diào)用,缺陷:可能會使目標(biāo)文件變大,優(yōu)勢:少了調(diào)用開銷,提高程序運行效率。
- inline對于編譯器而言只是一個建議,不同編譯器關(guān)于inline實現(xiàn)機制可能不同,一般建議:將函數(shù)規(guī)模較小(即函數(shù)不是很長,具體沒有準(zhǔn)確的說法,取決于編譯器內(nèi)部實現(xiàn))、不是遞歸、且頻繁調(diào)用的函數(shù)采用inline修飾,否則編譯器會忽略inline特性。
- 如果函數(shù)的規(guī)模較大(不建議展開),展開以后,編譯出來的可執(zhí)行程序就會變大。
- inline不建議聲明和定義分離,分離會導(dǎo)致鏈接錯誤。
因為inline被展開,就沒有函數(shù)地址了,鏈接就會找不到。
(可以理解為:內(nèi)聯(lián)函數(shù)沒有地址,它已經(jīng)被展開了)
【面試題】 宏的優(yōu)缺點?
優(yōu)點:
- 增強代碼的復(fù)用性。
- 提高性能。
缺點:
- 不方便調(diào)試宏。(因為預(yù)編譯階段進行了替換)
- 導(dǎo)致代碼可讀性差,可維護性差,容易誤用。
- 沒有類型安全的檢查 。
C++有哪些技術(shù)替代宏?
- 常量定義 換用const、enum
- 短小函數(shù)定義 換用內(nèi)聯(lián)函數(shù)
2.auto關(guān)鍵字
2.1auto簡介
隨著程序越來越復(fù)雜,程序中用到的類型也越來越復(fù)雜,經(jīng)常體現(xiàn)在:
- 類型難于拼寫
- 含義不明確導(dǎo)致容易出錯
有的同學(xué)也許也會想到,可以使用typedef 給較長的類型取別名,但是這種方法是有缺陷的,例如:
在早期C/C++中auto的含義是:使用auto修飾的變量,是具有自動存儲器的局部變量,但遺憾的是一直沒有人去使用它,大家可思考下為什么?
早期的auto關(guān)鍵字雖然是用來聲明具有自動存儲器的局部變量,但是我不寫auto它也是局部的,何必自找麻煩。
C++11中,標(biāo)準(zhǔn)委員會賦予了auto全新的含義即:auto不再是一個存儲類型指示符,而是作為一個新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時期推導(dǎo)而得。
typeid
是一個關(guān)鍵字,用來獲取一個表達式的類型信息。
注意:
使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據(jù)初始化表達式來推導(dǎo)auto的實際類型。因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編譯期會將auto替換為變量實際的類型。
2.2auto的注意事項
- auto與指針和引用結(jié)合起來使用
用auto聲明指針類型時,用auto和auto * 沒有任何區(qū)別,但用auto聲明引用類型時則必須加&
- 在同一行定義多個變量
當(dāng)在同一行聲明多個變量時,這些變量必須是相同的類型,否則編譯器將會報錯,因為編譯器實際只對第一個類型進行推導(dǎo),然后用推導(dǎo)出來的類型定義其他變量。
2.3auto不能推導(dǎo)的場景
- auto不能作為函數(shù)的參數(shù)
若auto作為參數(shù),那形參是什么類型呢?編譯器是不知道的,編譯時就不知道棧幀要開多大
- auto不能直接用來聲明數(shù)組
- 為了避免與C++98中的auto發(fā)生混淆(C++11中被廢棄了),C++11只保留了auto作為類型指示符的用法
- auto在實際中最常見的優(yōu)勢用法就是跟C++11提供的新式for循環(huán),還有l(wèi)ambda表達式等進行配合使用。
3.基于范圍的for循環(huán)(C++11)
- 范圍for簡介
在C++98中如果要遍歷一個數(shù)組,可以按照以下方式進行:
對于一個有范圍的集合而言,由程序員來說明循環(huán)的范圍是多余的,有時候還會容易犯錯誤。因此C++11中引入了基于范圍的for循環(huán)。for循環(huán)后的括號由冒號“ :”分為兩部分:第一部分是范圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。
要想改變數(shù)組中的元素,需要使用引用
注意:與普通循環(huán)類似,可以用continue來結(jié)束本次循環(huán),也可以用break來跳出整個循環(huán)。
- 范圍for的使用條件
- for循環(huán)迭代的范圍必須是確定的
對于數(shù)組而言,就是數(shù)組中第一個元素和最后一個元素的范圍;對于類而言,應(yīng)該提供begin和end的方法,begin和end就是for循環(huán)迭代的范圍。
注意:以下代碼就有問題,因為for的范圍不確定
void TestFor(int array[]){for(auto& e : array)//errorcout<< e <<endl;}
4.指針空值nullptr(C++11)
如果一個指針沒有合法的指向,我們基本都是按照如下方式對其進行初始化
void TestPtr()
{int* p1 = NULL;int* p2 = 0;// ……
}
NULL實際是一個宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
可以看到,NULL可能被定義為字面常量0,或者被定義為無類型指針(void)的常量*。不論采取何種定義,在使用空值的指針時,都不可避免的會遇到一些麻煩,比如:
程序本意是想通過f(NULL)調(diào)用指針版本的f(int*)函數(shù),但是由于NULL被定義成0,因此與程序的初衷相悖。
在C++98中,字面常量0既可以是一個整形數(shù)字,也可以是無類型的指針(void*)常量,但是編譯器默認(rèn)情況下將其看成是一個整形常量,如果要將其按照指針方式來使用,必須對其進行強轉(zhuǎn)(void*)0。
-
在使用nullptr表示指針空值時,不需要包含頭文件,因為nullptr是C++11作為新關(guān)鍵字引入的。
-
在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節(jié)數(shù)相同。
-
為了提高代碼的健壯性,在后續(xù)表示指針空值時建議最好使用nullptr。