文章目錄👑作者主頁:@安 度 因
🏠學(xué)習(xí)社區(qū):安度因的學(xué)習(xí)社區(qū)
📖專欄鏈接:C++修煉之路
一、前言如果無聊的話,就來逛逛 我的博客棧 吧! 🌹
大家好呀,我是 a n d u i n anduin anduin 。今天為大家?guī)砹说谝黄?C++ 文章,接下來 a n d u i n anduin anduin 會和大家一起學(xué)習(xí) C++ ,共同進步,共同成長!
C++語言建立在C的基礎(chǔ)之上。C++ 容納進去了面向?qū)ο缶幊趟枷耄⒃黾恿嗽S多有用的庫,以及編程范式等。這些使得 C++ 更加強大。
所以我們在 C++ 入門時,會學(xué)習(xí)很多瑣碎的語法,這些實際上就是在對 C 添磚加瓦,和填 “坑”。
對于 C++ 的重點,其實有兩方面,一塊是我們?nèi)腴T結(jié)束后要學(xué)習(xí)的類和對象,還有一部分就是stl
標準模板庫。這些我在以后都會重點講解。
而 C++ 的歷史我也就不多說了,我們今天的重點是講解知識,所以對歷史有興趣的小伙伴可以去查閱一下資料。
說了這么多,其實就是因為是 C++ 開篇哈哈哈,得把之后的內(nèi)容交待一下,相信有的小伙伴已經(jīng)迫不及待了,所以我們這就開始學(xué)習(xí) C++ 入門第一篇 。
二、第一個 C++ 程序在學(xué)習(xí)一門語言時,我們總是會先使用該語言編寫 “hello world” 程序,意味著打開了新世界,所以在開始我們的 C++ 之旅前,我們也寫個程序:
#includeusing namespace std;
int main()
{cout<< "hello world"<< endl;
return 0;
}
這就是 C++ 的 hello world 寫法,但是我們有沒有考慮過他為什么能打印出 “hello world” ?
這里的namespace
是什么,打印內(nèi)容的那一句代碼又是什么意思?這些可能我們可能都沒想過。如果你對這些還不太了解,或是比較生疏,那么恭喜你,本文非常適合像你我這樣的初學(xué)者,學(xué)習(xí)完這篇文章后,就可以大致想清楚這個程序的意思了。
C++一共有63個關(guān)鍵字,其中包含 C語言的32個關(guān)鍵字。
接下來我們就來認識一下它們:
asm | do | if | return | try | continue |
---|---|---|---|---|---|
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explict | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protect | this | volatile | while |
delete | goto | reinterpret_cast |
數(shù)量大約是我們學(xué)習(xí) C 語言時的兩倍。
我們這邊就是見一見,之后文章中都會講到~
四、命名空間接下來我們講解的就是namespace
命名空間。
命名空間的作用:在C/C++中,變量、函數(shù)和后面要學(xué)到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存在于全局作用域中,可能會導(dǎo)致很多沖突。使用命名空間的目的是對標識符的名稱進行本地化,以避免命名沖突或名字污染。
對于 C 語言,是無法解決命名沖突的,舉個例子:
rand
是 c 語言中取隨機數(shù)的一個庫函數(shù)名,在沒有引頭文件:#include
的情況下,我們可以使用rand
來定義變量。
但是一旦引了頭文件,就會發(fā)生報錯:
這就是 命名沖突 。這種情況實際上很常見,比如定義變量時可能會和庫里的名字沖突;在與他人合作時,可能多個人定義的名字之間也會沖突。
而通過命名空間,就可以輕松解決這個問題。
1、命名空間的定義定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對 {} 即可,{} 中即為命名空間的成員。
我們定義出的命名空間就像一個域,就像局部域和全局域一樣,每個域之間不相互影響,我們可以把命名空間叫做命名空間域。
命名空間域只影響使用,不影響生命周期。
所以在不同的namespace
中的成員就不會互相沖突。
命名空間有 四個特點 :
下面逐個演示一下:
1、2特點:
namespace anduin // 名字就是我
{int val = 10;
int solve()
{int returnvalue = 20;
return returnvalue;
}
}
3特點:
namespace anduin
{int foo = 100;
namespace guldan
{int fooo = 1000;
}
}
4特點:
在工程中,用定義同樣的命名空間:
在.c
文件中包含頭文件,編譯運行時,兩個命名空間就會合并:
這里就相當(dāng)于用 tool.h 中的print
函數(shù)將 test.h 中的max
打印了出來。
命名空間的使用的關(guān)鍵為 域作用限定符::
,就是我們上面 4 特點中像個骰子一樣的::
。
::
的左邊為域,如果有命名空間域,則限定訪問命名空間域中的內(nèi)容,如果域左邊為空,訪問的就是全局域,會直接到全局范圍內(nèi)找::
右邊的變量或其他。
舉個::
訪問全局域的例子 :
我們知道,C/C++ 為局部優(yōu)先原則,默認先從局部找,但是::
就直接將域限定到了全局域,找到就使用,找不到就報錯。所以打印的為全局的a = 2
。
如果在命名沖突的情況下,就可以將沖突的部分放到不同的域,通過域作用限定符來訪問命名空間,::
左邊就放命名空間,右邊就是命名空間中的成員,通過這種方式來解決問題 ,我們再舉個例子:
我們之前學(xué)過數(shù)據(jù)結(jié)構(gòu),知道鏈式隊列中是要使用到鏈表的,假如此刻我們有兩個頭文件:
如果同時包含頭文件,且定義相同類型名字Node
的節(jié)點,通過命名空間就可以成功定義:
我們看到是可以成功定義的。
這里 struct 放命名空間的前面是因為沖突的是Node
,struct
是一個前綴,::
修飾的是沖突的部分。
嵌套命名空間的使用 :
通過::
不斷訪問命名空間,找到print
函數(shù)和a
完成對數(shù)據(jù)的打印。
通過我們上面了解了命名空間的使用,其實發(fā)現(xiàn)有時使用很繁瑣,需要不停的::
展開,所以命名空間還有別的展開方式。
命名空間一共有三種展開方式:
對于這塊的講解呢,就可以回歸我們第一個 C++ 程序的代碼了。這就既能解決我們的疑惑,又能講解知識點。
#includeusing namespace std;
int main()
{cout<< "hello world"<< endl;
return 0;
}
實際上通過上面的學(xué)習(xí)我們可以知道:其實std
就是一個命名空間,為了防止命名沖突,C++ 之父在發(fā)明是就給它包好了一個空間,就是std
。
指定命名空間訪問:
指定命名空間就是一個個展開嘛,直接上代碼:
全局展開 :
全局展開就是using namespace std
,直接將std
在全局展開了,所以使用的時候就無須使用::
進行逐個展開,可以直接使用。
打個比方,比如沒展開,就會直接在全局找這個變量;但是如果展開,就不僅在全局找,還會到命名空間找。展開相當(dāng)于影響了編譯時的查找規(guī)則。
但是實際上這種展開方式并不好,因為命名空間,就是為了防止沖突而建立。這邊就相當(dāng)于直接把命名空間拆開來了。
所以對于這種展開我認為在平常練習(xí)代碼,或者是刷題時很好用,但是對于寫工程就不適合了。所以在之后的講解知識點的時候,我大多還是全局展開,但是小伙伴們需要注意區(qū)分一下使用場景。
部分展開 :
綜合上面兩種方案,還有一種就是部分展開,對命名空間某個常用成員進行展開,比如:
假如cout
常用,我就部分展開cout
;對于endl
我就不進行展開,還是指定訪問。
總結(jié) :
命名空間的展開就是為了使用的方便,對于不同的情況有不同的展開方式:
對于 C++ 的輸入和輸出其實是很復(fù)雜的,其中涉及到運算符重載等知識,以現(xiàn)在博主的水平可能說的還不是很清楚,所以我們這邊就大體介紹一下,知道怎么用就行。等以后理解透徹了,我會再把它但對拎出來講解。
1、cin / cout / endl 的簡單理解樣例:
#includeusing namespace std;
int main()
{int num = 0;
cin >>num;
cout<< num<< endl;
return 0;
}
說明:
- cout 和 cin是全局的流對象,endl 是特殊的 C++ 符號,表示換行輸出,等價于 ‘\n’ 。它們都包含在包含 頭文件中。
- 使用 cout 標準輸出對象(控制臺)和 cin 標準輸入對象(鍵盤)時,必須包含 頭文件以及按命名空間使用方法使用 std 庫。
- << 是流插入運算符,>>是流提取運算符。在進行輸出時,通常寫作 cout<< ,我們可以理解為是把數(shù)據(jù)流入 cout ,也就是流入我們程序運行起來的黑框中;在進行輸入時,通常寫作 cin >>,同理,可以理解為從黑框中提取數(shù)據(jù)到變量中。
- cout 和 cin 分別為 ostream 和 istream 的對象,<< 和 >>則涉及到運算符重載,實際上并不簡單。
我們甚至初學(xué)時,可以直接理解,cout<< 就是輸出,cin >>就是輸入。
下面,再演示一下 endl 等價于換行 :
2、printf / scanf 和 cout / cin 適用場景我們在寫 C++ 時,有時候會穿插著 C 語言寫,就拿 cout 和 cin 來說,它們的效率和方便性其實十分優(yōu)秀,比如 自動識別類型 :
這樣就省去了格式化的控制,大大優(yōu)化了代碼體驗。
但是 cout / cin 也有不太方便的情況,就比如控制精度這一方面,cout
輸出時就有點麻煩,這時使用printf
就很方便:
3、提速技巧對兩組輸入輸出的使用還是看個人喜好,個人使用的舒適度才是最重要的。我是偏向于 cin 和 cout 一點,畢竟玩 C++ 嘛!
由于 C++ 需要兼容 C ,所以需要保證一些緩沖區(qū)等的同步,所以有時 cin 和 cout 速度會相對較 scanf 和 printf 較慢,所以可以通過關(guān)掉同步來對 cin 和 cout 進行提速,在寫一些算法題時,博主經(jīng)常用 hhh :
ios::sync_with_stdio(false); // 關(guān)掉同步,提速 cin
cout.tie(NULL); // 提速 cout
但是請注意,一旦用了這兩句代碼 scanf 和 printf 就無法使用了!
六、缺省參數(shù)缺省參數(shù)相當(dāng)于又給 C 語言填上了一個 “坑” 。
1、缺省參數(shù)簡介缺省參數(shù)有時也被叫做默認參數(shù)。
缺省參數(shù)是聲明或定義函數(shù)時為函數(shù)的參數(shù)指定一個缺省值。在調(diào)用該函數(shù)時,如果沒有指定實參則采用該形參的缺省值,否則使用指定的實參。
在 C++ 中,支持給 函數(shù)形參賦值 的情況,例如:
#includeusing namespace std;
void Func(int a = 2)
{cout<< a<< endl;
}
int main()
{Func(1);
Func();
return 0;
}
這時a
就為缺省參數(shù)。
這里就相當(dāng)于給參數(shù)提供了一個缺省值,如果不進行傳參,就會直接使用缺省參數(shù)的缺省值;如果傳參,則使用傳遞的參數(shù)。
而缺省參數(shù)又分為兩類:全缺省參數(shù) 和 半缺省參數(shù) 。
2、全缺省參數(shù)全缺省參數(shù)就是所有參數(shù)都具有缺省值 ,所以函數(shù)調(diào)用十分隨意輕松。
舉個例子:
以上例子就把Func
的傳參方式都涵蓋了。若主動傳參,傳遞的參數(shù)從函數(shù)第一個函數(shù)開始,依次傳遞。
使用缺省值,必須從右往左連續(xù)使用:
例如全缺省參數(shù)這樣傳參:Func(, 2, )
就是錯誤的,傳參必須連續(xù),缺省值使用必須從右往左連續(xù)使用 !
半缺省參數(shù)也叫部分缺省,必須從右往左連續(xù)缺省 。
下面給出正確定義和錯誤定義:
下面再看看使用方式:
4、缺省參數(shù)的優(yōu)點缺省參數(shù)讓函數(shù)使用更加靈活,就拿之前我們數(shù)據(jù)結(jié)構(gòu)的例子來說,比如我們當(dāng)初寫棧時,當(dāng)棧初始化時,可以開辟空間,也可以不開辟空間。
#includeusing namespace std;
struct Stack
{int* a;
int top;
int capacity;
};
void StackInit(struct Stack* p)
{p->a = (int*)malloc(sizeof(int) * 100); // 空間開定 100
p->top = 0;
p->capacity = 100;
}
int main()
{Stack st;
StackInit(&st);
return 0;
}
這種寫法有一個缺點,就是空間寫定了,就只能是開 100 個整形空間;如果想開辟兩個大小不同的棧就沒辦法了,開大了浪費,開小了不夠用。
實在沒辦法就是再增加一個參數(shù)??墒窃黾訁?shù),如果對于無需求傳參的使用者來說,又是一件麻煩事,所以也不太可行。
但是如果這時使用缺省參數(shù),就可以解決這個問題:
當(dāng)然缺省參數(shù)的作用遠不止于此,之后我們會發(fā)現(xiàn)這個缺省參數(shù)真的牛!
5、缺省參數(shù)注意點一共四點:
下面我們來講一下第二點和第三點:
第二點 :
缺省參數(shù)是不能在函數(shù)聲明和定義的時候同時出現(xiàn)的,至于原因嘛,是規(guī)定。
比如 test.h 中聲明了缺省參數(shù),在 tool.cpp 中定義了,并在 test.cpp 中調(diào)用:
會報錯,并且,無論兩邊的缺省值改為什么值都是報錯。
千萬不要定義的時候給,聲明的時候不給這樣可以,這樣本質(zhì)上就錯了,聲明的函數(shù)都沒有缺省值,那么定義的函數(shù)又怎么會有呢?
我們平時使用缺省參數(shù),是在聲明時給缺省值。
這樣就沒問題了。
第三點 :
七、結(jié)語到這里,本篇文章就到此結(jié)束了。學(xué)習(xí)到這,大家對 “hello world” 程序在干什么也可以說個差不多了。
其實我們到這里也可以發(fā)現(xiàn) C++ 語法的一個特點就是精細、可控度高。但是如果控制度不夠,就會失控,所以 C++ 語法其實并不簡單。但是換句話說,沒什么事情是可以不努力就成功的, a n d u i n anduin anduin 以后會帶著大家滿滿啃下 C++ 語法,讓我們一起努力!
如果覺得 a n d u i n anduin anduin 寫的不錯的話,可以點贊 + 收藏 + 評論支持一下哦!
那么我們下期見!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧