摘要:中包含的即為命名空間的成員。使用輸入輸出更方便,不需增加數(shù)據(jù)格式控制,比如整形,字符可以連續(xù)輸出,表示換行缺省參數(shù)備胎,就是給汽車準(zhǔn)備一個(gè)備用輪胎,一旦那個(gè)輪子爆胎或者出了問(wèn)題,備用輪胎就方便及時(shí)地取而代之,汽車就不至于中途拋錨。
1.前言
2.C++關(guān)鍵字
3.命名空間
????3.1.命名空間的定義
????3.2.命名空間的使用
4.C++的輸入和輸出
5.缺省參數(shù)
????5.1.缺省參數(shù)的概念
????5.2.缺省參數(shù)的分類
????5.3.缺省參數(shù)的注意點(diǎn)
6.函數(shù)重載
????6.1.函數(shù)重載的概念
????6.2.函數(shù)重載的注意點(diǎn)
????6.3.為什么C++支持函數(shù)重載------名字修飾
????6.4.小結(jié)
7.extern “C”
8.引用
????8.1.引用的概念
????8.2.引用的特性
????8.3.常引用
????8.4.引用做參數(shù)
????8.5.引用做返回值
9.內(nèi)聯(lián)函數(shù)
????9.1.概念
????9.2.特性
10.auto關(guān)鍵字(C++11)
11.范圍for
12.nullptr
相比于C語(yǔ)言的32個(gè)關(guān)鍵字,C++的關(guān)鍵字加至63個(gè),很大程度上拓展了C語(yǔ)言的功能。
在C/C++中,變量,函數(shù)和類都是大量存在的。這些變量,函數(shù),類都存在于全局作用域中,可能導(dǎo)致很多沖突。舉個(gè)例子,我們的命名的變量跟庫(kù)里的變量名,函數(shù)名沖突了。就會(huì)導(dǎo)致重命名的問(wèn)題。在實(shí)際大型項(xiàng)目的開發(fā)中,還存在同事之間定義的變量/函數(shù)/類型命名沖突的情況。
比如說(shuō),在頭文件
為了對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突和名字污染,namespace便應(yīng)運(yùn)而生了。
我們剛剛提到C++有63個(gè)關(guān)鍵字,幾乎比C語(yǔ)言多了一倍。那么,我們就來(lái)看看其中新增的一個(gè)關(guān)鍵字——namespace吧!
定義命名空間,我們就需要用到namespace關(guān)鍵字,后面跟命名空間的名字。然后接一對(duì){}即可。{}中包含的即為命名空間的成員。
比如說(shuō),我和小許合作開發(fā)一款社交軟件,我們都在自己的文件里定義了全局變量cq。那在鏈接的過(guò)程中,就會(huì)報(bào)重命名的錯(cuò)誤。于是,我們只好采用不同的命名空間來(lái)定義我們各自的cq變量啦!
我們?cè)谌侄x了命名空間C1和C2:
namespace C1 { int cq = 30;}namespace C2 { int cq = 80;}
不僅如此,我們還可以在命名空間里定義其他任意類型的變量以及函數(shù):
namespace n1 { char ch; int a; double b; struct book { char name[20]; int price; int number; }; int Add(int x, int y) { return x + y; }}
甚至還可以嵌套定義命名空間:
namespace n2{ int a; int b; namespace n3 { int Sub(int x, int y) { return x - y; } }}
最后,同一個(gè)工程中允許存在多個(gè)相同名稱的命名空間,編譯器會(huì)最后合成到同一個(gè)命名空間中。
namespace C1 { int cq = 30;}namespace C1 { int cp = 40;}
好了,我們定義了各自的命名空間里定義了各自的cq,那用的時(shí)候怎么引用cq變量呢?
今有命名空間N
namespace N { int a = 30; int b = 40; int c = 50;}
我們有三種方法來(lái)使用命名空間N中定義的變量
using namespace
直接將命名空間中的變量全部展開到全局using namespace N;
優(yōu)點(diǎn):無(wú)腦方便
缺點(diǎn):把定義的變量暴露出去了,容易造成命名污染
命名空間名稱
+域操作符 ::
在訪問(wèn)時(shí)指定命名空間cout << N::rand <<endl;
優(yōu)點(diǎn):不存在命名污染
缺點(diǎn):用起來(lái)太煩了
using
將部分命名空間成員展開using N::a;using N::b;
這樣既降低了命名污染的概率,又能在使用變量時(shí)偷懶了
初識(shí)一門新語(yǔ)言,我們按老規(guī)矩辦事!
#include using namespace std;int main(){ cout << "hello world!" << endl; return 0;}
于是,hello world!
便打印在了控制臺(tái)中了!
我們來(lái)認(rèn)識(shí)一下C++的輸入輸出運(yùn)算符
cin >> n;
cout << a[i];
注意:
cout<< "hello" << " " << "world" << "!" << endl;
備胎,就是給汽車準(zhǔn)備一個(gè)備用輪胎,一旦那個(gè)輪子爆胎或者出了問(wèn)題,備用輪胎就方便及時(shí)地取而代之,汽車就不至于中途拋錨。
顧名思義,這“感情備胎”就是給自己在感情的歸宿上像輪胎一樣,有多一個(gè)甚至多個(gè)備份,“感情備胎”一般多指愛(ài)情。
悄悄告訴你,C++的函數(shù)參數(shù)
也有備胎哦!
缺省參數(shù)是指在聲明或定義函數(shù)時(shí)給函數(shù)的參數(shù)指定一個(gè)默認(rèn)值
。
在調(diào)用該函數(shù)時(shí),如果沒(méi)有指定實(shí)參,就采用這個(gè)默認(rèn)值,否則就采用實(shí)參。
比如說(shuō),我們希望malloc/realloc有默認(rèn)開辟的大小。在希望使用默認(rèn)值的時(shí)候缺省參數(shù),不希望的時(shí)候傳一個(gè)自己想要的參數(shù)。
我們拿出以前寫過(guò)的棧的數(shù)據(jù)空間的初始化以及增容的代碼:
void StackBuy(Stack* ps, int init_num = 4){ assert(ps); ps->capacity = ps->capacity == 0 ? init_num : 2 * ps->capacity; StackDataType* tmp = (StackDataType*)realloc(ps->data, ps->capacity * sizeof(StackDataType)); if (tmp == NULL) { printf("realloc failed/n"); return; } ps->data = tmp;}
這里,我們讓棧的data的元素?cái)?shù)量默認(rèn)是4,但是如果你想要讓它是8或者16的時(shí)候,多傳一個(gè)參數(shù)就行了!
缺省參數(shù)可以分成全缺省參數(shù)和半缺省參數(shù)
void TestFunc(int a = 10, int b = 20, int c = 30){ cout<<"a = "<<a<<endl; cout<<"b = "<<b<<endl; cout<<"c = "<<c<<endl;}
void TestFunc(int a, int b = 10, int c = 20) { cout<<"a = "<<a<<endl; cout<<"b = "<<b<<endl; cout<<"c = "<<c<<endl;}
void TestFunc(int a, int b = 10, int c) { cout<<"a = "<<a<<endl; cout<<"b = "<<b<<endl; cout<<"c = "<<c<<endl;}
int a = 10
僅需在聲明或定義的地方寫一次就行了。
常量
或者全局變量
。自然語(yǔ)言中,一個(gè)詞可以有多重含義,人們可以通過(guò)上下文來(lái)判斷該詞真實(shí)的含義,即該詞被重載了。
學(xué)校期末考試考完了,出考場(chǎng)后:
學(xué)霸:“考試完了?!?br /> 學(xué)渣:“考試完了。”
嘿嘿,雖然這兩句話讀起來(lái)一樣,但表達(dá)的意思可不一樣哦!
C++里面也有一函數(shù)多義的情況!
函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中
聲明幾個(gè)功能類似的同名函數(shù)
,這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù)
或 類型
或 順序
)必須不同,常用來(lái)處理實(shí)現(xiàn)功能類似數(shù)據(jù)類型不同的問(wèn)題
int Add(int left, int right) { return left + right;}double Add(double left, double right) { return left + right;}long Add(long left, long right) { return left + right;}
int Add(int n1, int n2){ return n1 + n2;}int Add(int n1, int n2, int n3){ return n1 + n2 + n3;}
int Add(int n1, double n2){ return n1 + n2;}int Add(double n1, int n2){ return n1 + n2;}
請(qǐng)?zhí)貏e注意,返回值不同,函數(shù)名及參數(shù)相同的函數(shù)不能重載!
short Add(short left, short right) { return left + right;}int Add(short left, short right){ return left + right;}
這就不屬于函數(shù)重載
我們說(shuō)函數(shù)重載是C語(yǔ)言不具有的功能,而C++添加了這個(gè)功能?
函數(shù)重載究竟是怎么實(shí)現(xiàn)的呢?
這就要從我們的底層函數(shù)調(diào)用講起了
在C/C++中,一個(gè)程序要運(yùn)行起來(lái),分為預(yù)處理,編譯,匯編,鏈接四個(gè)步驟
讓我們尤其來(lái)關(guān)注鏈接
這一步
鏈接時(shí),當(dāng)一個(gè)文件f1的某一行代碼調(diào)用了文件f2中的函數(shù)a時(shí),編譯器看到f1調(diào)用了a,但是f1中找不到a的地址,于是,編譯器就去f2的符號(hào)表中尋找a的地址
,發(fā)現(xiàn)能夠找到,然后便把a(bǔ)和f1鏈接到一起
那么編譯器根據(jù)什么去尋找函數(shù)的呢?
答案是 通過(guò)編譯后的函數(shù)名修飾
,對(duì)應(yīng)函數(shù)的地址,通過(guò)地址,最后找到函數(shù)
我們?cè)贚inux下分別使用gcc和g++編譯器看一下文件a.c和test.c
鏈接后的反匯編源碼
我們來(lái)看C語(yǔ)言編譯器gcc編譯鏈接后的結(jié)果:
我們可以看到,gcc編譯器的函數(shù)名修飾只與函數(shù)名本身有關(guān)而與函數(shù)參數(shù)無(wú)關(guān),所以C語(yǔ)言不支持函數(shù)重載,因?yàn)榧词怪剌d了你也無(wú)法讓編譯器去通過(guò)參數(shù)的不同在鏈接時(shí)找到不同的函數(shù)!
我們來(lái)看C++編譯器g++編譯鏈接后的結(jié)果:
我們可以看到,g++編譯器通過(guò)函數(shù)名修飾規(guī)則將符號(hào)表中的函數(shù)符號(hào)修飾成了_Z3Addii
的形式
_Z3
代表函數(shù)名長(zhǎng)度
Add
代表函數(shù)名
ii
代表有2個(gè)參數(shù)int和int
這樣參數(shù)不同的同名函數(shù)在符號(hào)表中被修飾成了不同的符號(hào),這就能在鏈接時(shí)輕松找到不同函數(shù)了!
通過(guò)這里就理解了C語(yǔ)言沒(méi)辦法支持重載,因?yàn)橥瘮?shù)沒(méi)辦法區(qū)分。
而C++是通過(guò)函數(shù)修飾規(guī)則來(lái)區(qū) 分,只要參數(shù)不同,修飾出來(lái)的名字就不一樣,就支持了重載。
另外我們也理解了,為什么函數(shù)重載要求參數(shù)不同!而跟返回值沒(méi)關(guān)系。
C++編譯器能識(shí)別C++函數(shù)名修飾規(guī)則,也能識(shí)別C函數(shù)名的修飾規(guī)則
有的時(shí)候,在C++工程中可能需要將某些函數(shù)按C的風(fēng)格編譯,那么,我們只要在函數(shù)前面加 extern “C”
,意思是告訴編譯器,將該函數(shù)按C語(yǔ)言規(guī)則來(lái)編譯
請(qǐng)注意,extern “C”
要在函數(shù)聲明以及定義的地方都加上,不能只加一個(gè)地方,否則就會(huì)報(bào)錯(cuò)!
先看一段代碼:
int main(){ int a = 10; int& ra = a;}
這里,ra就是a的引用。
引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。
比如,特朗普本名唐納德·特朗普,但在中國(guó),被叫做懂王,懂王就是他的別名
引用的格式如下:
類型& 引用變量名(對(duì)象名) = 引用實(shí)體;
int& ra;
int a = 10; int& ra = a; int& ra2 = a; int& rra = ra;
int a = 10; int& ra = a; int b = 20; ra = b;
ra = b;并不是讓ra從a的引用變成b的引用,而是將b賦值給ra
首先我們提一句話:
引用時(shí),別名的權(quán)限能夠減小或者不變,但不能放大
void TestConstRef() { const int a = 10; int& ra = a; //a被const修飾,表示a不能被改;而ra是a的引用,ra并沒(méi)有說(shuō)明自己不能被改,這時(shí)ra的權(quán)限被放大了,所以編譯報(bào)錯(cuò)}void TestConstRef() { const int a = 10; const int& ra = a; //這樣寫才是對(duì)的}
void TestConstRef() { int& ra = 10; //10是常量不能被修改,而ra卻是可以被修改,權(quán)限被放大了 const int& ra = 10; //這樣寫才是對(duì)的}
void TestConstRef() { double d =1.234; int& rd = d; //這里涉及到整型提升,將double轉(zhuǎn)換為int時(shí),提升完了的值存放在一個(gè)具有常性的臨時(shí)變量里,所以右邊是常數(shù),左邊是變量,左邊權(quán)限過(guò)大 const int& rd = d; //這樣寫才是對(duì)的}
所以引用前加const的好處是:
void Swap(int& left, int& right) { int temp = left; left = right; right = temp;}
先看一段錯(cuò)誤的代碼
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 << endl; return 0;}
運(yùn)行結(jié)果是7.
Why?
首先我們要知道函數(shù)被調(diào)用時(shí)會(huì)建立棧幀,函數(shù)被執(zhí)行完時(shí)棧幀就會(huì)被銷毀,那么返回值是怎么被從Add函數(shù)中返回到main函數(shù)中的呢?你不是說(shuō)Add函數(shù) 執(zhí)行完return c; 之后棧幀就被銷毀了嗎?c是怎么被傳遞出來(lái)的呢?哦,傳值返回時(shí),會(huì)為返回值開辟一個(gè)臨時(shí)變量,這個(gè)臨時(shí)變量還未還給操作系統(tǒng),那么使用引用返回,就能把這塊地址上的值返回出去。這還是很危險(xiǎn)的,萬(wàn)一已經(jīng)返還給操作系統(tǒng)了呢,內(nèi)存已經(jīng)被清空了呢?
于是,我們假設(shè)臨時(shí)變量的地址為0x8822ff44,第一次該地址上的值被置為3
同時(shí),ret對(duì)應(yīng)地址0x8822ff44
第二次調(diào)用Add,0x8822ff44上的值又被改為7
于是,ret對(duì)應(yīng)的值就是7了
在C++中,內(nèi)聯(lián)函數(shù)被用來(lái)替代宏函數(shù)
inline Add(int a, int b){ return a + b;}
以inline修飾的函數(shù)叫內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)在調(diào)用函數(shù)的地方展開,沒(méi)有建立棧幀的開銷,提升了程序運(yùn)行的效率。
來(lái)看這樣一段代碼:
int a = 1;char b = "y";auto c = a;auto d = b;
auto關(guān)鍵字幫助我們通過(guò)右邊的賦值,自動(dòng)判斷左邊聲明的變量的類型
優(yōu)點(diǎn):簡(jiǎn)化了代碼
缺點(diǎn):降低了代碼的可讀性
我們可以通過(guò)打印 typeid(變量).name() 來(lái)查看變量的類型
請(qǐng)注意:
int main() { int x = 10; auto a = &x; auto* b = &x; auto& c = x;}
int main(){ auto a = 3, c =4.0;}
void TestAuto(auto a) {}
void TestAuto() { int a[] = {1,2,3}; auto b[] = {4,5,6};}
auto不能用來(lái)聲明數(shù)組,因?yàn)榫幾g器不知道要申請(qǐng)多少字節(jié)的空間,后面的 3 究竟是short還是int還是long long?
對(duì)于一個(gè)有范圍的集合而言,由程序員來(lái)說(shuō)明循環(huán)的范圍是多余的,有時(shí)候還會(huì)容易犯錯(cuò)誤。
因此C++11中 引入了基于范圍的for循環(huán)。for循環(huán)后的括號(hào)由冒號(hào)“ :”分為兩部分:
第一部分是范圍內(nèi)用于迭代的變量,
第二部分則表示被迭代的范圍。
注意:for循環(huán)迭代的范圍必須是確定的
int main() { int arr[] = { 1,2,3,4,5,6 }; for (auto e : arr) cout << e << endl;}
好的編程習(xí)慣應(yīng)該是,在聲明一個(gè)變量的時(shí)候,給它賦一個(gè)合適的初值。
在對(duì)指針進(jìn)行初始化的時(shí)候,我們?cè)贑語(yǔ)言中常常這樣做:
int p = NULL;
NULL在C語(yǔ)言里是空指針,值為0
,類型是(void*)
,代表地址0x00000000
而我們看到C的頭文件
#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void*)0)#endif#endif
這段代碼告訴我們,我們用C編譯器,NULL就是0處的地址;用C++編譯器,NULL就是一個(gè)字面常量0,沒(méi)有指針的屬性
以下情況下,NULL的使用就會(huì)產(chǎn)生麻煩:NULL被當(dāng)作int 類型的0,而不是0x00000000
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;}
于是,C++11引入了新關(guān)鍵字 nullptr
,代表0處地址
注意:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121539.html
文章目錄 一.快速入門二.C++ 語(yǔ)法三.省略命名空間四.C++輸出(打印文本)五.C++新行(換行)六.C++注釋 一.快速入門 運(yùn)行如下程序: #include using namespace std;int main() { cout
摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...
摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...
摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...
摘要:本書主要圍繞一系列逐漸復(fù)雜的程序問(wèn)題,以及用以解決這些問(wèn)題的語(yǔ)言特性展開講解。你不只學(xué)到的函數(shù)和結(jié)構(gòu),也會(huì)學(xué)習(xí)到它們的設(shè)計(jì)目的和基本原理。因此我們把精力集中在最有價(jià)值的地方。本書不僅是對(duì)模板的權(quán)威解釋,而且本書還深入地介紹了其他一般的思想。 C++ 入門教程(41課時(shí)) - 阿里云大學(xué) C+...
閱讀 3386·2021-11-10 11:36
閱讀 3278·2021-10-08 10:21
閱讀 2907·2021-09-29 09:35
閱讀 2455·2021-09-22 16:06
閱讀 4035·2021-09-09 09:33
閱讀 1359·2019-08-30 15:44
閱讀 3203·2019-08-30 10:59
閱讀 3015·2019-08-29 15:32