? 關(guān)于學(xué)c++有一個(gè)很有意思的段子,網(wǎng)傳學(xué)c++只需要21天即可,前面10天學(xué)了c++基礎(chǔ),然后到21天還在學(xué)習(xí)對象,接口,多態(tài)。然后學(xué)著學(xué)著就兩年了,兩年后開始可以大量編寫代碼,然后與相關(guān)程序員侃侃而談。學(xué)到10年后,開始研究物理理論。20年后開始研究生物學(xué)了。40年后,運(yùn)用全部知識編程序制作了一個(gè)時(shí)空穿梭機(jī)。然后跑回到40年前,把做出21天學(xué)c++這個(gè)決定的自己殺了。
成都創(chuàng)新互聯(lián)公司成立于2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站制作、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元汨羅做網(wǎng)站,已為上家服務(wù),為汨羅各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575當(dāng)然這個(gè)僅僅是個(gè)玩笑,但是側(cè)面也反應(yīng)出學(xué)習(xí)c++不是一時(shí)半會的。有的大佬的也將學(xué)習(xí)c++分成4個(gè)層次。第一個(gè)層次,C++基礎(chǔ)(平平常常),。第二個(gè)層次,正確高效的使用C++ (駕輕就熟)。第三個(gè)層次,深入解讀C++ (出神入化)。第四個(gè)層次,研究C++ (返璞歸真)。它相對許多語言復(fù)雜,而且難學(xué)難精,雖然學(xué)習(xí)C++有難度,但也是相當(dāng)有趣且有滿足感的。
這時(shí)候有人開始對自己選擇開始懷疑了,認(rèn)為生命如此短暫,掌握技藝卻要如此長久。同時(shí)我們身邊也有很多販賣焦慮的,周圍充斥著程序員生命周期短暫的煙霧彈--30歲后就面臨這失業(yè)。其實(shí)不然,通過程浩大佬,看到文章《Is Programming Knowledge Related To Age?》這篇論文介紹到了關(guān)于年齡的看法,程浩大佬認(rèn)為(1)程序員技術(shù)能力上升是可以到50歲或60歲的。(2)老程序員在獲取新技術(shù)上的能力并不比年輕的程序員差。充滿焦慮,急于求成的人只是想呆在井底思維封閉而且想走捷徑速成。這篇文獻(xiàn)給與我一樣正在學(xué)習(xí),并且準(zhǔn)備為技術(shù)和編程執(zhí)著和堅(jiān)持的人。因?yàn)閷λ龅氖虑榈睦斫庠缴?,你就會做的越好?/p>
目錄
前言
c++的發(fā)展史?
c++的版本
c++在的工作領(lǐng)域
操作系統(tǒng)以及大型系統(tǒng)軟件開發(fā)
服務(wù)器端開發(fā) ?
游戲開發(fā)
嵌入式和物聯(lián)網(wǎng)領(lǐng)域
數(shù)字圖像處理
人工智能
分布式應(yīng)用
C++關(guān)鍵字
命名空間
實(shí)際工程應(yīng)用中:?
命名空間的作用:
命名空間需求展示
命名空間定義
命名空間使用
C++輸入&輸出
c++的《hello world》
輸入&輸出說明:
輸入&輸出展示?????
std命名空間的使用慣例
缺省參數(shù)?
缺省參數(shù)概念
缺省參數(shù)分類
函數(shù)重載
函數(shù)重載概念?
C++支持函數(shù)重載的原理--名字修飾(name Mangling)
引用
引用概念
引用特性
常引用
使用場景?
傳值、傳引用效率比較
值和引用的作為返回值類型的性能比較?
引用和指針的區(qū)別?
? 1925年1月1日,當(dāng)時(shí)AT&T總裁,華特·基佛德(Walter Gifford)收購了西方電子公司的研究部門,成立一個(gè)叫做“貝爾電話實(shí)驗(yàn)室公司”的獨(dú)立實(shí)體,后改稱貝爾實(shí)驗(yàn)室。
當(dāng)時(shí)美國貝爾實(shí)驗(yàn)室是晶體管、激光器、太陽能電池、發(fā)光二極管、數(shù)字交換機(jī)、通信衛(wèi)星、電子數(shù)字計(jì)算機(jī)、C語言、UNIX操作系統(tǒng)、蜂窩移動(dòng)通信設(shè)備等通信方向,自1925年以來,貝爾實(shí)驗(yàn)室共獲得兩萬五千多項(xiàng)專利,現(xiàn)在,平均每個(gè)工作日獲得三項(xiàng)多專利。
隨著科技的創(chuàng)新,丹尼斯里奇所寫的c語言已經(jīng)不能滿足程序員的需求,因?yàn)镃語言是結(jié)構(gòu)化和模塊化的語言,適合處理較小規(guī)模的程序。對于復(fù)雜的問題,規(guī)模較大的程序,需要高度的抽象和建模時(shí),C語言則不合適。為了解決軟件危機(jī), 20世紀(jì)80年代, 計(jì)算機(jī) 界提出了OOP(object oriented programming:面向?qū)ο?思想,支持面向?qū)ο蟮某绦蛟O(shè)計(jì)語言 應(yīng)運(yùn)而生。
c語言之父--丹尼斯里奇的照片
1979年,當(dāng)時(shí)Bjarne Stroustrup正在準(zhǔn)備他的博士畢業(yè)論文,他有機(jī)會使用一種叫做Simula 的語言。顧名思義,Simula語言的主要作用是仿真。Simula67是Simula語言的一種變種,被公認(rèn)是首款支持面向?qū)ο蟮恼Z言。Stroustrup發(fā)現(xiàn)面向?qū)ο蟮乃枷雽τ谲浖_發(fā)非常有用,但是因Simula語言執(zhí)行效率低,其實(shí)用性不強(qiáng)。
不久之后,Stroustrup開始著手“C with Classes”的研發(fā)工作,“C with Classes”表明這種新語言是在C基礎(chǔ)上研發(fā)的,是C語言的超集。C語言以其高可移植性而廣受好評,且程序執(zhí)行速度以及底層函數(shù)的性能不受程序移植的影響,Stroustrup要做的就是將面向?qū)ο蟮乃枷胍隒語言。新語言的初始版本除了包括C語言的基本特征之外,還具備類、簡單繼承、內(nèi)聯(lián)機(jī)制、函數(shù)默認(rèn)參數(shù)以及強(qiáng)類型檢查等特性。
1982年,本賈尼·斯特勞斯特盧普(Bjarne Stroustrup)博士在C語言的基礎(chǔ)上引入并擴(kuò)充了面向?qū)ο蟮母拍?,發(fā)明了一 種新的程序語言。為了表達(dá)該語言與C語言的淵源關(guān)系,命名為C++。因此:C++是基于C語言而 產(chǎn)生的,它既可以進(jìn)行C語言的過程化程序設(shè)計(jì),又可以進(jìn)行以抽象數(shù)據(jù)類型為特點(diǎn)的基于對象的程序設(shè)計(jì),還可以進(jìn)行面向?qū)ο蟮某绦蛟O(shè)計(jì)。
c++之父--本賈尼·斯特勞斯特盧普的照片? ? ? ? ? ??
c++的版本階段 | 內(nèi)容 |
---|---|
C with classes | 類及派生類、公有和私有成員、類的構(gòu)造和析構(gòu)、友元、內(nèi)聯(lián)函數(shù)、賦值運(yùn)算符 重載等 |
C++1.0 | 添加虛函數(shù)概念,函數(shù)和運(yùn)算符重載,引用、常量等 |
C++2.0 | 更加完善支持面向?qū)ο?,新增保護(hù)成員、多重繼承、對象的初始化、抽象類、靜 態(tài)成員以及const成員函數(shù) |
C++3.0 | 進(jìn)一步完善,引入模板,解決多重繼承產(chǎn)生的二義性問題和相應(yīng)構(gòu)造和析構(gòu)的處 理 |
C++98 | C++標(biāo)準(zhǔn)第一個(gè)版本,絕大多數(shù)編譯器都支持,得到了國際標(biāo)準(zhǔn)化組織(ISO)和美 國標(biāo)準(zhǔn)化協(xié)會認(rèn)可,以模板方式重寫C++標(biāo)準(zhǔn)庫,引入了STL(標(biāo)準(zhǔn)模板庫) |
C++03 | C++標(biāo)準(zhǔn)第二個(gè)版本,語言特性無大改變,主要:修訂錯(cuò)誤、減少多異性 |
C++05 | C++標(biāo)準(zhǔn)委員會發(fā)布了一份計(jì)數(shù)報(bào)告(Technical Report,TR1),正式更名 C++0x,即:計(jì)劃在本世紀(jì)第一個(gè)10年的某個(gè)時(shí)間發(fā)布 |
C++11 | 增加了許多特性,使得C++更像一種新語言,比如:正則表達(dá)式、基于范圍for循 環(huán)、auto關(guān)鍵字、新容器、列表初始化、標(biāo)準(zhǔn)線程庫等 |
C++14 | 對C++11的擴(kuò)展,主要是修復(fù)C++11中漏洞以及改進(jìn),比如:泛型的lambda表 達(dá)式,auto的返回值類型推導(dǎo),二進(jìn)制字面常量等 |
C++17 | 在C++11上做了一些小幅改進(jìn),增加了19個(gè)新特性,比如:static_assert()的文 本信息可選,F(xiàn)old表達(dá)式用于可變的模板,if和switch語句中的初始化器等 |
C++20 | 自C++11以來大的發(fā)行版,引入了許多新的特性,比如:模塊(Modules)、協(xié) 程(Coroutines)、范圍(Ranges)、概念(Constraints)等重大特性,還有對已有 特性的更新:比如Lambda支持模板、范圍for支持初始化等 |
C++23 | 制定ing |
通過上述不同版本,我們發(fā)現(xiàn)其實(shí)c++在更新迭代是非常慢的,而且多次更新的改進(jìn)也不是很大,所以先好多公司主流使用的還是c++98和c++11。好多都是這么形容c++的,好比修房子,他基礎(chǔ)搭建的非常好,但是向上修建的時(shí)候就比較偷工減料了,房子上層也越修越窄。
好比迪拜--哈利法塔
現(xiàn)在大家對c++23版本也持有較大期待,因?yàn)闀瓉碓S多程序員夢寐以求的標(biāo)準(zhǔn)網(wǎng)絡(luò)庫。c++23版本離我們快要到了,有些許朋友會感到才學(xué)其他版本就要被遺棄了。不必?fù)?dān)憂,出來之后還沒有穩(wěn)定,大公司還需要測試之后才能廣泛使用,所以真正到使用其實(shí)還有很久。
c++在的工作領(lǐng)域 操作系統(tǒng)以及大型系統(tǒng)軟件開發(fā)所有操作系統(tǒng)幾乎都是C/C++寫的,許多大型軟件背后幾乎都是C++寫的,比如:
Photoshop、O?ce、JVM(Java虛擬機(jī))等,究其原因還是性能高,可以直接操控硬件。
服務(wù)器端開發(fā) ?后臺開發(fā):主要側(cè)重于業(yè)務(wù)邏輯的處理,即對于前端請求后端給出對應(yīng)的響應(yīng),現(xiàn)在主流采 用java,但內(nèi)卷化比較嚴(yán)重,大廠可能會有C++后臺開發(fā),主要做一些基礎(chǔ)組件,中間件、 緩存、分布式存儲等。服務(wù)器端開發(fā)比后臺開發(fā)跟廣泛,包含后臺開發(fā),一般對實(shí)時(shí)性要求 比較高的,比如游戲服務(wù)器、流媒體服務(wù)器、網(wǎng)絡(luò)通訊等都采用C++開發(fā)的。
游戲開發(fā)PC平臺幾乎所有的游戲都是C++寫的,比如:魔獸世界、傳奇、CS、跑跑卡丁車等,市面上 相當(dāng)多的游戲引擎都是基于C++開發(fā)的,比如:Cocos2d、虛幻4、DirectX等。三維游戲領(lǐng) 域計(jì)算量非常龐大,底層的數(shù)學(xué)全都是矩陣變換,想要畫面精美、內(nèi)容豐富、游戲?qū)崟r(shí)性 搞,這些高難度需求無疑只能選C++語言。比較知名廠商:騰訊、網(wǎng)易、完美世界、巨人網(wǎng) 絡(luò)等。
嵌入式和物聯(lián)網(wǎng)領(lǐng)域嵌入式:就是把具有計(jì)算能力的主控板嵌入到機(jī)器裝置或者電子裝置的內(nèi)部,能夠控制這些 裝置。比如:智能手環(huán)、攝像頭、掃地機(jī)器人、智能音響等。 談到嵌入式開發(fā),大家最能想到的就是單片機(jī)開發(fā)(即在8位、16位或者32位單片機(jī)產(chǎn)品或者 裸機(jī)上進(jìn)行的開發(fā)),嵌入式開發(fā)除了單片機(jī)開發(fā)以外,還包含在soc片上、系統(tǒng)層面、驅(qū)動(dòng) 層面以及應(yīng)用、中間件層面的開發(fā)。 常見的崗位有:嵌入式開發(fā)工程師、驅(qū)動(dòng)開發(fā)工程師、系統(tǒng)開發(fā)工程師、Linux開發(fā)工程 師、固件開發(fā)工程師等。 知名的一些廠商,比如:以華為、vivo、oppo、小米為代表的手機(jī)廠;以紫光展銳、樂鑫為 代表的芯片廠;以大疆、??低?、大華、CVTE等具有自己終端業(yè)務(wù)廠商;以及海爾、海 信、格力等傳統(tǒng)家電行業(yè)。 隨著5G的普及,物聯(lián)網(wǎng)(即萬物互聯(lián),)也成為了一種新興勢力,比如:阿里lot、騰訊lot、京 東、百度、美團(tuán)等都有硬件相關(guān)的事業(yè)部。
數(shù)字圖像處理數(shù)字圖像處理中涉及到大量數(shù)學(xué)矩陣方面的運(yùn)算,對CPU算力要求比較高,主要的圖像處理 算法庫和開源庫等都是C/C++寫的,比如:OpenCV、OpenGL等,大名鼎鼎的Photoshop就是C++寫的。
人工智能一提到人工智能,大家首先想到的就是python,認(rèn)為學(xué)習(xí)人工智能就要學(xué)習(xí)python,這個(gè) 是誤區(qū),python中庫比較豐富,使用python可以快速搭建神經(jīng)網(wǎng)絡(luò)、填入?yún)?shù)導(dǎo)入數(shù)據(jù)就 可以開始訓(xùn)練模型了。但人工智能背后深度學(xué)習(xí)算法等核心還是用C++寫的。
分布式應(yīng)用近年來移動(dòng)互聯(lián)網(wǎng)的興起,各應(yīng)用數(shù)據(jù)量業(yè)務(wù)量不斷攀升;后端架構(gòu)要不斷提高性能和并發(fā) 能力才能應(yīng)對大信息時(shí)代的來臨。在分布式領(lǐng)域,好些分布式框架、文件系統(tǒng)、中間組件等 都是C++開發(fā)的。對分布式計(jì)算影響極大的Hadoop生態(tài)的幾個(gè)重量級組件:HDFS、zookeeper、HBase等,也都是基于Google用C++實(shí)現(xiàn)的GFS、Chubby、BigTable。包括分 布式計(jì)算框架MapReduce也是Google先用C++實(shí)現(xiàn)了一套,之后才有開源的java版本。
C++關(guān)鍵字C++總計(jì)63個(gè)關(guān)鍵字,C語言32個(gè)關(guān)鍵字。如果還想回顧一下c語言的關(guān)鍵字就可以點(diǎn)擊看看。最開始我只需知道有哪些,后面的用法我們也會專門的仔細(xì)講。
命名空間 實(shí)際工程應(yīng)用中:??在編寫大型工程序中,往往是由多個(gè)人共同完成的,如果大家命名時(shí)想到一起去了就會產(chǎn)生處理程序中常見的同名沖突。還有可能我們使用到的函數(shù)庫,因?yàn)橛行┖瘮?shù)我們也不會經(jīng)常使用,忘記之后也有可能會跟庫函數(shù)的命名相同,這樣在程序中就會出現(xiàn)命名沖突(即重復(fù)定義)。在C/C++中,變量、函數(shù)和后面要學(xué)到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存 在于全局作用域中,可能會導(dǎo)致很多沖突。這個(gè)時(shí)候就會大量使用到命名空間。
命名空間的作用:建立了一些相互分隔的作用域,將一些全局實(shí)體分隔開來,以免產(chǎn)生名字沖突。可以根據(jù)需要設(shè)置多個(gè)命名空間,每個(gè)命名空間代表一個(gè)不同的命名空間域,不同的命名空間不能同名。? ? ??
使用命名空間的目的是對標(biāo)識符的名稱進(jìn)行本地化, 以避免命名沖突或名字污染,namespace關(guān)鍵字的出現(xiàn)就是針對這種問題的。
命名空間需求展示? 當(dāng)我們編寫如下代碼,就會出現(xiàn)編譯報(bào)錯(cuò):error C2365: “rand”: 重定義;以前的定義是“函數(shù)” 。這個(gè)問題c語言是無法解決的,但是C++提出了namespace來解決 。
#include#includeint rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
命名空間定義定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對{}即可,{}中即為命名空間的成員。命名空間的名字,一般開發(fā)中是用項(xiàng)目名字做命名空間名。
1.正常的命名空間定義
namespace test
{
// 命名空間中可以定義變量/函數(shù)/類型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
2.命名空間可以嵌套
namespace test1
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
namespace test2
{
int a;
int b;
int Sub(int left, int right)
{
return left - right;
}
}
}
3.同一個(gè)工程中允許存在多個(gè)相同名稱的命名空間,編譯器最后會合成同一個(gè)命名空間中。
通過預(yù)處理后,文件test.h與test.c都將展開。這里用到namespace,它將不同文件的test合成一個(gè)test,這里的test就相當(dāng)于有兩個(gè)兩個(gè)函數(shù)。
test.h文件
namespace test
{
int Sub(int left, int right)
{
return left - right;
}
}
test.cpp文件
#define _CRT_SECURE_NO_WARNINGS
#include#include "test.h"
namespace test
{
int Add(int left, int right)
{
return left + right;
}
}
int main()
{
int a = 2;
int b = 3;
int c=test::Add(a, b);
printf("%d", c);
return 0;
}
命名空間使用1.加命名空間名稱及作用域限定符
namespace N
{
int a = 0;
int b = 2;
}
int main()
{
printf("%d",N:: a);
return 0;
}
2.使用using將命名空間中某個(gè)成員引入
namespace N
{
int a = 0;
int b = 2;
}
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
3.? 使用using namespace 命名空間名稱引入??
namespace N
{
int a = 0;
int b = 2;
int Add(int left, int right)
{
return left + right;
}
}
using namespce N;
int main()
{
? ?printf("%d\n", N::a);
? ?printf("%d\n", b);
? ?Add(10, 20);
? ?return 0; ? ?
}
C++輸入&輸出? 你還記得學(xué)習(xí)c語言時(shí)“printf”的你嗎?還記得你寫下第一個(gè)《hello world》的時(shí)候嗎?一路學(xué)過來c語言全靠它發(fā)聲,如果忘記了,那就記下當(dāng)下c++的親切的問候!
c++的《hello world》#include// std是C++標(biāo)準(zhǔn)庫的命名空間名,C++將標(biāo)準(zhǔn)庫的定義實(shí)現(xiàn)都放到這個(gè)命名空間中
using namespace std;
int main()
{
cout<<"Hello world!!!"<
輸入&輸出說明:輸入&輸出展示?????1.使用cout標(biāo)準(zhǔn)輸出對象(控制臺)和cin標(biāo)準(zhǔn)輸入對象(鍵盤)時(shí),與使用printf與scanf需要包含頭文件
一樣,而這里包含< iostream >頭文件以及按命名空間使用方法使用std。 2.<<是流插入運(yùn)算符,>>是流提取運(yùn)算符。 輸出時(shí),選擇流插入運(yùn)算符;輸入時(shí),選擇流提取運(yùn)算符。
3.cout和cin是全局的流對象,endl是特殊的C++符號,表示換行輸出,他們都包含在包含< iostream >頭文件中。
4. 使用C++輸入輸出更方便,不需要像printf/scanf輸入輸出時(shí)那樣,需要手動(dòng)控制格式。C++的輸入輸出可以自動(dòng)識別變量類型。
我們發(fā)現(xiàn)運(yùn)用cin與cout是不需要加輸入輸出類型,那么對于控制浮點(diǎn)的精度問題來怎么解決呢?因?yàn)閏++是包容c語言的用法的,比如當(dāng)我們需要控制浮點(diǎn)數(shù)輸出精度,控制整形輸出進(jìn)制格式?,那我們就還是可以選擇用c語言的用法。
#includeusing namespace std;
int main()
{
? int a;
? double b;
? char c;
? ?
? // 可以自動(dòng)識別變量的類型
? cin>>a;
? cin>>b>>c;
? ?
? cout<
std命名空間的使用慣例缺省參數(shù)? 缺省參數(shù)概念1. 在日常練習(xí)中,建議直接using namespace std即可,這樣就很方便。
2. using namespace std展開,標(biāo)準(zhǔn)庫就全部暴露出來了,如果我們定義跟庫重名的類型/對 象/函數(shù),就存在沖突問題。該問題在日常練習(xí)中很少出現(xiàn),但是項(xiàng)目開發(fā)中代碼較多、規(guī)模 大,就很容易出現(xiàn)。所以建議在項(xiàng)目開發(fā)中使用,像std::cout這樣使用時(shí)指定命名空間 + using std::cout展開常用的庫對象/類型等方式。
? 缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值 ,在調(diào)用該函數(shù)時(shí),如果沒有指定實(shí)參則采用該默認(rèn)值,否則使用指定的實(shí)參。
#includeusing namespace std;
void Func(int a = 0)
{
cout<< a<< endl;
}
int main()
{
Func(); // 沒有傳參時(shí),使用參數(shù)的默認(rèn)值
Func(10); // 傳參時(shí),使用指定的實(shí)參
return 0;
}
說明:
? 使用c語言時(shí),我們是不能給參數(shù)進(jìn)行設(shè)置初始值的--語法要求;當(dāng)我們使用時(shí)會出報(bào)錯(cuò),參數(shù)的初始化錯(cuò)誤。但是在c++中是可以的,相當(dāng)于直接給函數(shù)的參數(shù)設(shè)置了一個(gè)初始值,當(dāng)調(diào)用函數(shù)不傳實(shí)參時(shí)就會得到我們設(shè)置的初始值。
缺省參數(shù)分類1.全缺省參數(shù)
將全部參數(shù)設(shè)置初始值
#includeusing namespace std;
void Func(int a = 10, int b = 20, int c = 30)
{
cout<< "a = "<< a<< endl;
cout<< "b = "<< b<< endl;
cout<< "c = "<< c<< endl;
}
int main()
{
Func();
Func(100);
Func(100,200);
Func(100,200,300);
return 0;
}
2.半缺省參數(shù)
將一部分參數(shù)設(shè)置初始值
void Func(int a, int b = 10, int c = 20)
{
cout<< "a = "<< a<< endl;
cout<< "b = "<< b<< endl;
cout<< "c = "<< c<< endl;
}
int main()
{
//Func();//因?yàn)榈谝粋€(gè)參數(shù)沒有設(shè)置初始值,所以第一個(gè)參數(shù)需要穿實(shí)參
Func(100);
Func(100,200);
Func(100,200,300);
return 0;
}
注意:
1. 半缺省參數(shù)必須從右往左依次來給出,不能間隔著給
2. 缺省值必須是常量或者全局變量
3. C語言不支持(編譯器不支持)
4. 缺省參數(shù)不能在函數(shù)聲明和定義中同時(shí)出現(xiàn)
第4點(diǎn)說明
//a.h文件
?void Func(int a = 10);
?
?// a.cpp文件
?void Func(int a = 20)
{}
?
?// 注意:如果生命與定義位置同時(shí)出現(xiàn),恰巧兩個(gè)位置提供的值不同,那編譯器就無法確定到底該
用那個(gè)缺省值。
函數(shù)重載? 函數(shù)重載跟我們生活中一詞多意很像,人們可以通過上下文或者語境來判斷該詞真實(shí)的含義,即該詞被重載了。好比如你喜歡的女孩對你說:你很好!或者成為女朋友了對你說:我很好!
函數(shù)重載概念?是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù)或類型或類型順序)不同,常用來處理實(shí)現(xiàn)功能類似數(shù)據(jù)類型不同的問題。
1.參數(shù)類型不同?
int Add(int left, int right)
{
cout<< "int Add(int left, int right)"<< endl;
return left + right;
}
double Add(double left, double right)
{
cout<< "double Add(double left, double right)"<< endl;
return left + right;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
return 0;
}
2、參數(shù)個(gè)數(shù)不同
void f()
{
cout<< "f()"<< endl;
}
void f(int a)
{
cout<< "f(int a)"<< endl;
}
int main()
{
f();
f(10);
return 0;
}
3、參數(shù)類型順序不同
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, 'a');
f('a', 10);
return 0;
}
C++支持函數(shù)重載的原理--名字修飾(name Mangling)在這里我們必須知道這幾過程:預(yù)處理、編譯、匯編、鏈接。重拾:c--程序環(huán)境與預(yù)處理。首先我們知道預(yù)處理是將各個(gè)文件代碼展開,然后把該替換的替換了,該刪除的刪除了。然后進(jìn)入編譯階段,將c語言代碼轉(zhuǎn)換成匯編指針,在這過程中有詞法分析,語法分析等。再這就匯編階段,它將匯編代碼轉(zhuǎn)換為計(jì)算機(jī)認(rèn)識的二進(jìn)制指令,這里重點(diǎn)就是會生成符號表,符號表中有函數(shù)名和地址。
下面就是編譯階段,在linux下gcc環(huán)境和g++環(huán)境編譯完成階段的兩端代碼。
采用C語言編譯器編譯后結(jié)果 :
這里我們仔細(xì)觀察得到,在linux下,采用gcc編譯完成后,這里的函數(shù)名沒有任何修飾,如果我們用兩個(gè)相同的函數(shù)名,編譯器是無法辨別的。
采用C++編譯器編譯后結(jié)果:
那么在linux下,采用g++編譯完成后,我們發(fā)現(xiàn)函數(shù)是得到修飾的。編譯器將函數(shù)參 數(shù)類型信息添加到修改后的名字中。這里好比兩個(gè)紅玫瑰蘋果,一個(gè)是紅玫瑰125克,一個(gè)是紅玫瑰124克。他們都可以裝在一個(gè)蘋果籃子里,但是都能取分開。
我們在c++環(huán)境下,通過對函數(shù)名字的修飾((name Mangling),讓相同的函數(shù)不同的功能得以實(shí)現(xiàn)。只要參數(shù)不同,修飾出來的名字就不一樣,就支持了重載。但是不同系統(tǒng)函數(shù)修飾規(guī)則是有不同的。
在最后鏈接階段,通過連接器(Linker)將所有二進(jìn)制形式的目標(biāo)文件和系統(tǒng)組件組合成一個(gè)可執(zhí)行文件。
引用 引用概念引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會為引用變量開辟內(nèi)存空 間,它和它引用的變量共用同一塊內(nèi)存空間。
這里就比好:蔡徐坤,在籃球上粉絲都愛稱:“雞,你太美”。其他方面上,粉絲親切叫一聲:“哥哥或者坤坤”。
類型& 引用變量名(對象名) = 引用實(shí)體;
#includevoid TestRef()
{
int a = 10;
int& ra = a;//<====定義引用類型
printf("%p\n", &a);
printf("%p\n", &ra);
}
int main()
{
TestRef();
return 0;
}
注意:引用類型必須和引用實(shí)體是同種類型的
引用特性1. 引用在定義時(shí)必須初始化
2. 一個(gè)變量可以有多個(gè)引用
3. 引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體
void TestRef()
{
int a = 10;
// int& ra; ? // (1)該條語句編譯時(shí)會出錯(cuò)
int b = 20;
int& ra = a;
int& ra = b;//(3)報(bào)錯(cuò):重定義;多次初始化
int& rra = a;
printf("%p %p %p\n", &a, &ra, &rra);
}
int main()
{
TestRef();
return 0;
}
常引用const 類型 & 引用名;
作用:是不希望對所引用的內(nèi)容進(jìn)行修改。
void TestConstRef()
{
const int a = 10;
//int& ra = a; ? //(1) 該語句編譯時(shí)會出錯(cuò),a為常量
const int& ra = a;
// int& b = 10; //(2) 該語句編譯時(shí)會出錯(cuò),b為常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // (3)該語句編譯時(shí)會出錯(cuò),類型不同
const int& rd = d;
}
解釋:
出錯(cuò)1:
a被const修飾,a的權(quán)限被縮小,而這里卻想將a的權(quán)限擴(kuò)大,在操作系統(tǒng)中權(quán)限只能縮小,不能被擴(kuò)大,解決辦法const int& ra=a;
出錯(cuò)2:
引用的值必須為左值,b為常量。常量是一個(gè)真實(shí)值,可讀,所以b為右值。那么左值相當(dāng)于地址。因?yàn)檫@里b是在進(jìn)行初始化,是一個(gè)臨時(shí)對象。所以這里錯(cuò)誤就是右值引用。右值進(jìn)行引用的時(shí)候需要被const修飾,const int& b = 10;
右值引用簡單理解,就是綁定到左值的引用,右值引用的特點(diǎn)是:它將讓其所綁定的右值重獲新生,即使該右值本身是一個(gè)臨時(shí)變量,但是它本身卻不能綁定任何左值。
錯(cuò)誤3:
d為double類型,引用不能改變類型。那么這里加const讓rd變成可讀,相當(dāng)于對d建立臨時(shí)變量,以前我們遇到的截?cái)?,提升都屬于通建立臨時(shí)變量解決的問題的。
運(yùn)用:
void func(const int& b)
{
cout<< "b:"<< &b<< endl;
int c = b;
cout<< "c:"<< &c<< endl;
c++;
cout<< "c value"<< c<< endl;
}
int main()
{
int a = 10;
cout<< "a:"<< &a<< endl;
func(a);
return 0;
}
可以看出a和b的地址一樣,而c與b的地址不一樣,可以修改c的值,但是無法修改b的內(nèi)容。
使用場景?1.做參數(shù)
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
int main()
{
int a = 5, b = 6;
Swap(a,b);
cout<< a<<" "<< b<< endl;
return 0;
}
以前我們學(xué)習(xí)c語言是用的指針,現(xiàn)在我們學(xué)習(xí)c++就可以用引用替代,而且書寫代碼更加簡潔。?
2.做返回值
這里引用做返回值使用是就需要特別小心,因?yàn)闀l(fā)生函數(shù)棧幀,當(dāng)函數(shù)被銷毀的時(shí)候,他原來的空間就會被覆蓋,那么有可能會我們用得到的返回值,再去進(jìn)行訪問時(shí)就找到原來那個(gè)值。
列如:
這里使用static,返回值n是靜態(tài)變量,存放的空間是在全局區(qū)(代碼區(qū))而不是棧區(qū)。
int& Count()
{
? static int n = 0;
? n++;
? // ...
? return n;
}
那么使用下面代碼會發(fā)生什么呢?
int& Add(int a, int b)
{
? ?int c = a + b;
? ?return c;
}
int main()
{
? ?int& ret = Add(1, 2);
? ?Add(3, 4);
? ?cout<< "Add(1, 2) is :"<< ret<
我們發(fā)現(xiàn)第二次使用的Add函數(shù)時(shí),ret的結(jié)果發(fā)生了改變。這里主要是因?yàn)閮纱味际鞘褂玫腁dd函數(shù),開辟的空間是一樣大,所以第一次使用函數(shù)的空間被第二次使用函數(shù)的空間所覆蓋。原本是3的值,第二次進(jìn)行訪問的時(shí)候原位置是7了。
如果想象不出這個(gè)過程,通過圖來理解:
我們這里只是一種情況,其實(shí)它有三種情況:(1)原來的值 (2)隨機(jī)值 (3)被覆蓋的值
int& Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int& ret = Add(1, 2);
cout<< "Add(1, 2) is :"<< ret<< endl;
cout<< "Add(1, 2) is :"<< ret<< endl;
Add(3, 4);
cout<< "Add(1, 2) is :"<< ret<< endl;
return 0;
}
那么如何理解這三種情況呢?
其實(shí)很好理解,因?yàn)樘N近我們生活了。當(dāng)你一個(gè)人去開房,走的時(shí)候發(fā)現(xiàn)你華為手機(jī)掉在房間了,然后你回去找,第一種情況:你找到了你自己的手機(jī)。第二種情況:阿姨打掃了,原來的地方?jīng)]有你的手機(jī),可能放在前臺了。第三中情況:別人已經(jīng)入住了,你原來放手機(jī)的位置放的是蘋果手機(jī)(別人的)。
我們要記住這個(gè)是錯(cuò)誤代碼展示,只是讓我們深入理解之后不在編寫出這樣的代碼。
正確代碼:
//方法一
int Add(int a, int b)
{
int c = a + b;
return c;
}
//方法二
int& Add(int a, int b)
{
static int c = a + b;
return c;
}
傳值、傳引用效率比較結(jié)論:
如果函數(shù)返回時(shí),出了函數(shù)作用域,如果返回對象還在(還沒還給系統(tǒng)),則可以使用引用返回,如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。
以值作為參數(shù)或者返回值類型,在傳參和返回期間,函數(shù)不會直接傳遞實(shí)參或者將變量本身直接返回,而是傳遞實(shí)參或者返回變量的一份臨時(shí)的拷貝,因此用值作為參數(shù)或者返回值類型,效率是非常低下的,尤其是當(dāng)參數(shù)或者返回值類型非常大時(shí),效率就更低。
#includestruct A{
int a[10000];
};
void TestFunc1(A a){
}
void TestFunc2(A& a){
}
void TestRefAndValue(){
A a; // 以值作為函數(shù)參數(shù)
size_t begin1 = clock();
for (size_t i = 0; i< 10000; ++i)
TestFunc1(a);
size_t end1 = clock();
// 以引用作為函數(shù)參數(shù)
size_t begin2 = clock();
for (size_t i = 0; i< 10000; ++i)
TestFunc2(a);
size_t end2 = clock();
// 分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間
cout<< "TestFunc1(A)-time:"<< end1 - begin1<< endl;
cout<< "TestFunc2(A&)-time:"<< end2 - begin2<< endl;
}
int main()
{
TestRefAndValue();
return 0;
}
值和引用的作為返回值類型的性能比較?傳值和指針在作為傳參以及返回值類型上效率相差很大。
#includestruct A{ int a[10000]; };
A a;// 值返回
A TestFunc1() {
return a;
}
// 引用返回
A& TestFunc2(){
return a;
}
void TestReturnByRefOrValue(){
// 以值作為函數(shù)的返回值類型
size_t begin1 = clock();
for (size_t i = 0; i< 100000; ++i)
TestFunc1();
size_t end1 = clock();
// 以引用作為函數(shù)的返回值類型
size_t begin2 = clock();
for (size_t i = 0; i< 100000; ++i)
TestFunc2();
size_t end2 = clock();
// 計(jì)算兩個(gè)函數(shù)運(yùn)算完成之后的時(shí)間
cout<< "TestFunc1 time:"<< end1 - begin1<< endl;
cout<< "TestFunc2 time:"<< end2 - begin2<< endl;
}
int main()
{
TestReturnByRefOrValue();
return 0;
}
引用和指針的區(qū)別?在語法概念上引用就是一個(gè)別名,沒有獨(dú)立空間,和其引用實(shí)體共用同一塊空間。
int main(){
int a = 10;
int& ra = a;
cout<< "&a = "<< &a<< endl;
cout<< "&ra = "<< &ra<< endl;
return 0;
}
在語法上,他們的地址都是一樣的,所以共用一塊空間。但是在底層實(shí)現(xiàn)上實(shí)際是有空間的,因?yàn)橐檬前凑罩羔樂绞絹韺?shí)現(xiàn)的。
int main(){
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}
引用和指針的語法對比圖:
我們來看下引用和指針的匯編代碼對比:
在底層引用與指針,當(dāng)變量很小的時(shí)候都是用寄存器存儲的,相當(dāng)于開辟一塊臨時(shí)變量。?
引用和指針的不同點(diǎn):
內(nèi)聯(lián)函數(shù)1. 引用概念上定義一個(gè)變量的別名,指針存儲一個(gè)變量地址。
2. 引用在定義時(shí)必須初始化,指針沒有要求
3. 引用在初始化時(shí)引用一個(gè)實(shí)體后,就不能再引用其他實(shí)體,而指針可以在任何時(shí)候指向任何一個(gè)同類型實(shí)體
4. 沒有NULL引用,但有NULL指針
5. 在sizeof中含義不同:引用結(jié)果為引用類型的大小,但指針始終是地址空間所占字節(jié)個(gè)數(shù)(32
位平臺下占4個(gè)字節(jié))
6. 引用自加即引用的實(shí)體增加1,指針自加即指針向后偏移一個(gè)類型的大小
7. 有多級指針,但是沒有多級引用
8. 訪問實(shí)體方式不同,指針需要顯式解引用,引用編譯器自己處理
9. 引用比指針使用起來相對更安全
? 在c語言中,我們?yōu)榱私鉀Q調(diào)用函數(shù)不開辟棧幀,我們經(jīng)常會使用到宏,但是使用宏是有缺陷的,1不能調(diào)試,2沒有類型安全檢查,3容易寫錯(cuò)。為了解決這些問題c++就使用內(nèi)聯(lián)函數(shù)。
宏與內(nèi)聯(lián)的比較#include#define Add(x,y) ((x)+(y))
inline int add(int x, int y)
{
return x + y;
}
int main()
{
int x = 10, y = 20;
int ret = Add(x, y);
int ret2 = add(x, y);
printf("%d\n",ret);
printf("%d\n", ret2);
return 0;
}
概念以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)調(diào) 用建立棧幀的開銷,內(nèi)聯(lián)函數(shù)提升程序運(yùn)行的效率。
如果在上述函數(shù)前增加inline關(guān)鍵字將其改成內(nèi)聯(lián)函數(shù),在編譯期間編譯器會用函數(shù)體替換函數(shù)的 調(diào)用。
查看方式:?
1. 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add
2. 在debug模式下,需要對編譯器進(jìn)行設(shè)置,否則不會展開(因?yàn)閐ebug模式下,編譯器默認(rèn)不 會對代碼進(jìn)行優(yōu)化,以下給出vs2013的設(shè)置方式)
特性1. inline是一種以空間換時(shí)間的做法,如果編譯器將函數(shù)當(dāng)成內(nèi)聯(lián)函數(shù)處理,在編譯階段,會 用函數(shù)體替換函數(shù)調(diào)用,缺陷:可能會使目標(biāo)文件變大,優(yōu)勢:少了調(diào)用開銷,提高程序運(yùn)行效率。
展開會用更多的寄存器,空間就會變大,這樣就會影響可執(zhí)行程序的大小--安裝包。
2. inline對于編譯器而言只是一個(gè)建議,不同編譯器關(guān)于inline實(shí)現(xiàn)機(jī)制可能不同,一般建議:將函數(shù)規(guī)模較小(即函數(shù)不是很長,具體沒有準(zhǔn)確的說法,取決于編譯器內(nèi)部實(shí)現(xiàn))、不是遞歸、且頻繁調(diào)用的函數(shù)采用inline修飾,否則編譯器會忽略inline特性。
當(dāng)函數(shù)長了之后展開會發(fā)聲代碼膨脹
3. inline不建議聲明和定義分離,分離會導(dǎo)致鏈接錯(cuò)誤。因?yàn)閕nline被展開,就沒有函數(shù)地址 了,鏈接就會找不到。 ?
// F.h
#includeusing namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
cout<< i<< endl;
}
// main.cpp
#include "F.h"
int main()
{
f(10);
return 0;
}
// 鏈接錯(cuò)誤:main.obj : error LNK2019: 無法解析的外部符號 "void __cdecl
f(int)" (?f@@YAXH@Z),該符號在函數(shù) _main 中被引用
auto關(guān)鍵字?隨著程序越來越復(fù)雜,程序中用到的類型也越來越復(fù)雜,經(jīng)常體現(xiàn)在:
1. 類型難于拼寫
2. 含義不明確導(dǎo)致容易出錯(cuò)
#include#include
std::map::iterator 是一個(gè)類型,但是該類型太長了,特別容 易寫錯(cuò)。聰明的同學(xué)可能已經(jīng)想到:可以通過typedef給類型取別名,比如: ?
#include #include
typedef std::mapstd::string, std::string>Map;
int main() {
Map m{
{
"apple", "蘋果" },{ "orange", "橙子" }, {"pear","梨"}
};
使用typedef給類型取別名確實(shí)可以簡化代碼,但是typedef有會遇到新的難題: 在編程時(shí),常常需要把表達(dá)式的值賦值給變量,這就要求在聲明變量的時(shí)候清楚地知道表達(dá)式的 類型。然而有時(shí)候要做到這點(diǎn)并非那么容易,因此C++11給auto賦予了新的含義。
auto簡介在早期C/C++中auto的含義是:使用auto修飾的變量,是具有自動(dòng)存儲器的局部變量,但遺憾的 是一直沒有人去使用它,大家可思考下為什么?
C++11中,標(biāo)準(zhǔn)委員會賦予了auto全新的含義即:auto不再是一個(gè)存儲類型指示符,而是作為一 個(gè)新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時(shí)期推導(dǎo)而得。
int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout<< typeid(b).name()<< endl;
cout<< typeid(c).name()<< endl;
cout<< typeid(d).name()<< endl;
//auto e; 無法通過編譯,使用auto定義變量時(shí)必須對其進(jìn)行初始化
return 0;
}
auto的使用細(xì)則【注意】
使用auto定義變量時(shí)必須對其進(jìn)行初始化,在編譯階段編譯器需要根據(jù)初始化表達(dá)式來推導(dǎo)auto的實(shí)際類型。因此auto并非是一種“類型”的聲明,而是一個(gè)類型聲明時(shí)的“占位符”,編譯器在編 譯期會將auto替換為變量實(shí)際的類型。
1. auto與指針和引用結(jié)合起來使用 用auto聲明指針類型時(shí),用auto和auto*沒有任何區(qū)別,但用auto聲明引用類型時(shí)則必須 加&
int main()
{
? ?int x = 10;
? ?auto a = &x;
? ?auto* b = &x;
? ?auto& c = x;
? ?cout<< typeid(a).name()<< endl;
? ?cout<< typeid(b).name()<< endl;
? ?cout<< typeid(c).name()<< endl;
? ?*a = 20;
? ?*b = 30;
? ? c = 40;
? ?return 0;
}
2. 在同一行定義多個(gè)變量 當(dāng)在同一行聲明多個(gè)變量時(shí),這些變量必須是相同的類型,否則編譯器將會報(bào)錯(cuò),因?yàn)榫幾g 器實(shí)際只對第一個(gè)類型進(jìn)行推導(dǎo),然后用推導(dǎo)出來的類型定義其他變量。 ??
void TestAuto()
{
? ?auto a = 1, b = 2;
? ?auto c = 3, d = 4.0; ?// 該行代碼會編譯失敗,因?yàn)閏和d的初始化表達(dá)式類型不同
}
auto不能推導(dǎo)的場景1. auto不能作為函數(shù)的參數(shù)
// 此處代碼編譯失敗,auto不能作為形參類型,因?yàn)榫幾g器無法對a的實(shí)際類型進(jìn)行推導(dǎo)
void TestAuto(auto a)
{}
2. auto不能直接用來聲明數(shù)組 ?
void TestAuto()
{
? ?int a[] = {1,2,3};
? ?auto b[] = {4,5,6};
}
3. 為了避免與C++98中的auto發(fā)生混淆,C++11只保留了auto作為類型指示符的用法
4. auto在實(shí)際中最常見的優(yōu)勢用法就是跟以后會講到的C++11提供的新式for循環(huán),還有
lambda表達(dá)式等進(jìn)行配合使用。
基于范圍的for循環(huán)(C++11) 范圍for的語法在C++98中如果要遍歷一個(gè)數(shù)組,可以按照以下方式進(jìn)行:
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;
}
對于一個(gè)有范圍的集合而言,由程序員來說明循環(huán)的范圍是多余的,有時(shí)候還會容易犯錯(cuò)誤。因 此C++11中引入了基于范圍的for循環(huán)。for循環(huán)后的括號由冒號“ :”分為兩部分:第一部分是范 圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。
void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array)
? ? e *= 2;
for(auto e : array)
? ? cout<< e<< " ";
return 0;
}
范圍for的使用條件?注意:
與普通循環(huán)類似,可以用continue來結(jié)束本次循環(huán),也可以用break來跳出整個(gè)循環(huán)。?
1. for循環(huán)迭代的范圍必須是確定的 對于數(shù)組而言,就是數(shù)組中第一個(gè)元素和最后一個(gè)元素的范圍;對于類而言,應(yīng)該提供begin和end的方法,begin和end就是for循環(huán)迭代的范圍。
注意:以下代碼就有問題,因?yàn)閒or的范圍不確定
void TestFor(int array[])
{
? ?for(auto& e : array)
? ? ? ?cout<< e<
2. 迭代的對象要實(shí)現(xiàn)++和==的操作。(關(guān)于迭代器這個(gè)問題,以后會講,現(xiàn)在提一下,沒辦法 講清楚,現(xiàn)在大家了解一下就可以了)
指針空值nullptr(C++11) C++98中的指針空值在良好的C/C++編程習(xí)慣中,聲明一個(gè)變量時(shí)最好給該變量一個(gè)合適的初始值,否則可能會出現(xiàn) 不可預(yù)料的錯(cuò)誤,比如未初始化的指針。如果一個(gè)指針沒有合法的指向,我們基本都是按照如下 方式對其進(jìn)行初始化:
void TestPtr()
{
int* p1 = NULL;
int* p2 = 0;
// ……
}
NULL實(shí)際是一個(gè)宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼: ?
#ifndef NULL
#ifdef __cplusplus
#define NULL ? 0
#else
#define NULL ? ((void *)0)
#endif
#endif
可以看到,NULL可能被定義為字面常量0,或者被定義為無類型指針(void*)的常量。不論采取何 種定義,在使用空值的指針時(shí),都不可避免的會遇到一些麻煩,比如:
void f(int)
{
cout<<"f(int)"<
注意:
1. 在使用nullptr表示指針空值時(shí),不需要包含頭文件,因?yàn)閚ullptr是C++11作為新關(guān)鍵字引入 的。
2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節(jié)數(shù)相同。
3. 為了提高代碼的健壯性,在后續(xù)表示指針空值時(shí)建議最好使用nullptr。
今天的知識到這里就完了,希望該文章能對各位朋友有一絲幫助!? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (全文完)?
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧