【C++】 C++入门和基础
? ? ? ? ????????????????????????????????????????????????什么是C++?
????????1982年,Bjarne Stroustrup博士在C語(yǔ)言的基礎(chǔ)上引入并擴(kuò)充了面向?qū)ο蟮母拍?#xff0c;發(fā)明了一種新的程序語(yǔ)言。為了表達(dá)該語(yǔ)言與C語(yǔ)言的淵源關(guān)系,命名為C++。因此:C++是基于C語(yǔ)言而產(chǎn)生的,它既可以進(jìn)行C語(yǔ)言的過(guò)程化程序設(shè)計(jì),又可以進(jìn)行以抽象數(shù)據(jù)類(lèi)型為特點(diǎn)的基于對(duì)象的程序設(shè)計(jì),還可以進(jìn)行面向?qū)ο蟮某绦蛟O(shè)計(jì)。
登高莫問(wèn)頂,途中耳目新!
文章目錄
- 一、C++的發(fā)展歷史和應(yīng)用領(lǐng)域
- 二、C++的關(guān)鍵字
- 三、命名空間
- 四、C++的輸入輸出
- 五、缺省參數(shù)
- 六、函數(shù)重載
- 七、C++的引用
- 八、內(nèi)聯(lián)函數(shù)
- 總結(jié)
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、C++的發(fā)展歷史和應(yīng)用領(lǐng)域
1.1、C++的起源
????????C語(yǔ)言是結(jié)構(gòu)化和模塊化的語(yǔ)言,適合處理較小規(guī)模的程序。對(duì)于復(fù)雜的問(wèn)題,規(guī)模較大的程序,需要高度 的抽象和建模時(shí),C語(yǔ)言則不合適。為了解決軟件危機(jī), 20世紀(jì)80年代, 計(jì)算機(jī)界提出了OOP(object oriented programming:面向?qū)ο?思想,支持面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言應(yīng)運(yùn)而生。之后便有了本賈尼博士等人設(shè)計(jì)出了C++這門(mén)語(yǔ)言。
1.2、C++發(fā)展史及歷代版本
? ? ? ??1979年,貝爾實(shí)驗(yàn)室的本賈尼等人試圖分析unix內(nèi)核的時(shí)候,試圖將內(nèi)核模塊化,于是在C語(yǔ)言的基礎(chǔ)上進(jìn)行擴(kuò)展,增加了類(lèi)的機(jī)制,完成了一個(gè)可以運(yùn)行的預(yù)處理程序,稱(chēng)之為C with classes。
1.3、C++的歷史版本
| ????????階段 | ????????????????????????????????????????????????????????????????內(nèi)容 |
| C with classes | 類(lèi)及派生類(lèi)、公有和私有成員、類(lèi)的構(gòu)造和析構(gòu)、友元、內(nèi)聯(lián)函數(shù)、賦值運(yùn)算符重載等 |
| C++1.0 | 添加虛函數(shù)概念,函數(shù)和運(yùn)算符重載,引用、常量等 |
| C++2.0 | 更加完善支持面向?qū)ο?#xff0c;新增保護(hù)成員、多重繼承、對(duì)象的初始化、抽象類(lèi)、靜態(tài)成員以 及const成員函數(shù) |
| C++3.0 | 進(jìn)一步完善,引入模板,解決多重繼承產(chǎn)生的二義性問(wèn)題和相應(yīng)構(gòu)造和析構(gòu)的處理 |
| C++98 | C++標(biāo)準(zhǔn)第一個(gè)版本,絕大多數(shù)編譯器都支持,得到了國(guó)際標(biāo)準(zhǔn)化組織(ISO)和美國(guó)標(biāo)準(zhǔn)化 協(xié)會(huì)認(rèn)可,以模板方式重寫(xiě)C++標(biāo)準(zhǔn)庫(kù),引入了STL(標(biāo)準(zhǔn)模板庫(kù)) |
| ··· | ···之后介紹重要版本 |
| C++11 | 增加了許多特性,使得C++更像一種新語(yǔ)言,比如:正則表達(dá)式、基于范圍for循環(huán)、auto 關(guān)鍵字、新容器、列表初始化、標(biāo)準(zhǔn)線程庫(kù)等 |
| C++14 | 對(duì)C++11的擴(kuò)展,主要是修復(fù)C++11中漏洞以及改進(jìn),比如:泛型的lambda表達(dá)式, auto的返回值類(lèi)型推導(dǎo),二進(jìn)制字面常量等 |
? ? ? ? 現(xiàn)階段我們常用的還是C++98和C++11;
1.4、C++的應(yīng)用領(lǐng)域
?1. 操作系統(tǒng)以及大型系統(tǒng)軟件開(kāi)發(fā)
2. 服務(wù)器端開(kāi)發(fā)
3. 人工智能
4. 網(wǎng)絡(luò)工具
5. 游戲開(kāi)發(fā)
6. 嵌入式領(lǐng)域
7. 數(shù)字圖像處理
8. 分布式應(yīng)用
9. 移動(dòng)設(shè)備
二、C++的關(guān)鍵字
1.1、C++關(guān)鍵字
????????(C++98) C++總計(jì)63個(gè)關(guān)鍵字,C語(yǔ)言32個(gè)關(guān)鍵字
三、?命名空間
3.1、命名空間的概念
????????在C/C++中,變量、函數(shù)和后面要學(xué)到的類(lèi)都是大量存在的,這些變量、函數(shù)和類(lèi)的名稱(chēng)將都存在于全局作 用域中,可能會(huì)導(dǎo)致很多沖突。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱(chēng)進(jìn)行本地化,以避免命名沖突或名字污染,namespace關(guān)鍵字的出現(xiàn)就是針對(duì)這種問(wèn)題的。
示例:如下,我們自己定義的rand和庫(kù)里的rand函數(shù)產(chǎn)生命名沖突
?3.2、命名空間的定義
????????定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì){}即可,{}中即為命名空間的成員。
? ? ? ? 注意點(diǎn):
? ? ? ?1、命名空間中的內(nèi)容,既可以定義變量,也可以定義函數(shù)
? ? ? ?2、命名空間還可以嵌套,同名的命名空間會(huì)被編譯器合并到一起。
3.3、命名空間嵌套的示例
#include<stdio.h> #include<stdlib.h> namespace jjx {namespace xiang{struct ListNode{int val;struct ListNode* next;};} }加域訪問(wèn)限定符訪問(wèn)使用示例:
#include<iostream>//放出來(lái),方便使用了,但是存在沖突風(fēng)險(xiǎn) //using namespace std; //std封C++庫(kù)的命名空間//放部分常用的 using std::cout; using std::endl; using std::cin; int main() { cout << "hello world" << endl;return 0; }注意:一個(gè)命名空間就定義了一個(gè)新的作用域,命名空間中的所有內(nèi)容都局限于該命名空間中
3.4命名空間的使用
1、加命名空間名稱(chēng)及作用域限定符????????::
2、使用using將命名空間中成員引入? ? ? ? using N::b;
3、使用using namespace 命名空間名稱(chēng)引入????????using namespce N;
四、C++的輸入輸出
4.1、C++是如何實(shí)現(xiàn)輸入輸出的例子:
#include<iostream>using namespace std; int main() {int a = 0;scanf("%d", &a);printf("%d\n", a);// >> 流提取運(yùn)算符,cin 是對(duì)象, >> 是運(yùn)算符重載,并且自動(dòng)識(shí)別輸入類(lèi)型cin >> a;// << 流插入運(yùn)算符cout << a;return 0; }說(shuō)明:
1. 使用cout標(biāo)準(zhǔn)輸出(控制臺(tái))和cin標(biāo)準(zhǔn)輸入(鍵盤(pán))時(shí),必須包含< iostream >頭文件以及std標(biāo)準(zhǔn)命名空間。
注意:早期標(biāo)準(zhǔn)庫(kù)將所有功能在全局域中實(shí)現(xiàn),聲明在.h后綴的頭文件中,使用時(shí)只需包含對(duì)應(yīng)頭文件即可,后來(lái)將其實(shí)現(xiàn)在std命名空間下,為了和C頭文件區(qū)分,也為了正確使用命名空間,規(guī)定C++頭文件不帶.h;舊編譯器(vc 6.0)中還支持<iostream.h>格式,后續(xù)編譯器已不支持,因此推薦使用
<iostream>+std的方式。
2. 使用C++輸入輸出更方便,不需增加數(shù)據(jù)格式控制,比如:整形--%d,字符--%c
cin中的>>是通過(guò)重載>>和模板實(shí)現(xiàn)自動(dòng)識(shí)別類(lèi)型。
五、缺省參數(shù)
5.1、?缺省參數(shù)概念
????????缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值。在調(diào)用該函數(shù)時(shí),如果沒(méi)有指定實(shí)參則采用該 默認(rèn)值,否則使用指定的實(shí)參。
類(lèi)似于備胎的概念:
缺省參數(shù)/默認(rèn)參數(shù) void Fun(int a = 0) {cout << a << endl; } int main() {Fun();//沒(méi)有傳參數(shù)的時(shí)候,使用參數(shù)的默認(rèn)值Fun(1);//傳參時(shí),使用指定的實(shí)參return 0; }?5.2、 缺省參數(shù)分類(lèi)
? ·全缺省參數(shù):
void Fun(int a = 10, int b = 20, int c = 30) {cout << "a =" << a << endl;cout << "b =" << b << endl;cout << "c =" << c << endl << endl; } int main() {Fun();Fun(1);Fun(1, 2);Fun(1, 2, 3);return 0; }?·半缺省參數(shù):
?注:
1. 半缺省參數(shù)必須從右往左依次來(lái)給出,不能間隔著給
2. 缺省參數(shù)不能在函數(shù)聲明和定義中同時(shí)出現(xiàn)
3. 缺省值必須是常量或者全局變量
4. C語(yǔ)言不支持(編譯器不支持)
void Fun(int a , int b = 20, int c = 30) {cout << "a =" << a << endl;cout << "b =" << b << endl;cout << "c =" << c << endl << endl; } int main() { // Fun();半缺省至少傳一個(gè)參數(shù)Fun(1);Fun(1, 2);Fun(1, 2, 3);return 0; }?缺省值必須是常量或者全局變量
void QueueInit(int n = 10);//申明給值 #include"Queue.h" void QueueInit(int n)//定義給值不可以,必須在申明給值 {cout << n << endl; } #include"Queue.h" int main() {QueueInit();//不給值默認(rèn)是10,如果是定義給值,則頭文件在這展開(kāi)時(shí)//編譯器找不到其默認(rèn)值,鏈接時(shí)找定義QueueInit(20);return 0; }六、函數(shù)重載
C語(yǔ)言不支持重載,C++支持重載!
C++是如何支持的?為什么C語(yǔ)言不能支持?
這里我們一起探索一下問(wèn)題的答案!
6.1、函數(shù)重載概念 :
函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能類(lèi)似的同名函數(shù),這些同名函數(shù)的 形參列表(參數(shù)個(gè)數(shù) 或 類(lèi)型 或 順序)必須不同,常用來(lái)處理實(shí)現(xiàn)功能類(lèi)似數(shù)據(jù)類(lèi)型不同的問(wèn)題
//C語(yǔ)言不支持同名函數(shù) //CPP支持同名函數(shù) //要求:參數(shù)名相同———— //參數(shù)不同:參數(shù)個(gè)數(shù)/類(lèi)型/順序 int Add(int left, int right) {return left + right; } double Add(double left, double right) {return left + right; } void f(int i, double d) {cout << "void f(int i, double d)" << endl; } void f(double i, int d) {cout << "void f(double i, int d)" << endl; } //示例二 void swap(int* p1, int* p2) {int x = *p1;*p1 = *p2;*p2 = x; } void swap(double* p1, double* p2) {double x = *p1;*p1 = *p2;*p2 = x; } int main() {cout << Add(1, 2) << endl;cout << Add(1.1, 2.2) << endl;f(1, 22.2);f(22.2, 1);int a = 0, b = 1;double c = 1.1, d = 2.2;swap(&a, &b);swap(&c, &d);return 0;}為什么C++支持函數(shù)重載,而C語(yǔ)言不支持函數(shù)重載呢?為此我們不得不提到一個(gè)新的概念名字修飾(name Mangling)。
6.2、 名字修飾(name Mangling)
在C/C++中,一個(gè)程序要運(yùn)行起來(lái),需要經(jīng)歷以下幾個(gè)階段:預(yù)處理、編譯、匯編、鏈接。
?????????1. 實(shí)際我們的項(xiàng)目通常是由多個(gè)頭文件和多個(gè)源文件構(gòu)成,而通過(guò)我們C語(yǔ)言階段學(xué)習(xí)的編譯鏈接,我們 可以知道,【當(dāng)前a.cpp中調(diào)用了b.cpp中定義的Add函數(shù)時(shí)】,編譯后鏈接前,a.o的目標(biāo)文件中沒(méi)有 Add的函數(shù)地址,因?yàn)锳dd是在b.cpp中定義的,所以Add的地址在b.o中。那么怎么辦呢?
????????2. 所以鏈接階段就是專(zhuān)門(mén)處理這種問(wèn)題,鏈接器看到a.o調(diào)用Add,但是沒(méi)有Add的地址,就會(huì)到b.o的符 號(hào)表中找Add的地址,然后鏈接到一起。(如果同學(xué)們忘記了上面過(guò)程,咋們老師要帶同學(xué)們回顧一下)
????????3. 那么鏈接時(shí),面對(duì)Add函數(shù),連接器會(huì)使用哪個(gè)名字去找呢?這里每個(gè)編譯器都有自己的函數(shù)名修飾規(guī)則。
示例:由于Windows下vs的修飾規(guī)則過(guò)于復(fù)雜,而Linux下gcc的修飾規(guī)則簡(jiǎn)單易懂
?g++(C++)的函數(shù)名修飾
gcc
?
6.3 、extern “C”
?在函數(shù)前加extern "C",意思是告訴編譯器, 將該函數(shù)按照C語(yǔ)言規(guī)則來(lái)編譯.
?
C++可以調(diào)用C的庫(kù),利用extern 是c++的語(yǔ)法
C也可以調(diào)用C++的庫(kù),但是很麻煩,需要條件編譯
下面就是條件編譯
小結(jié):為啥C++支持函數(shù)重載
????????了C語(yǔ)言沒(méi)辦法支持重載,因?yàn)橥瘮?shù)沒(méi)辦法區(qū)分。而C++是通過(guò)函數(shù)修飾規(guī)則來(lái)區(qū) 分,只要參數(shù)不同,修飾出來(lái)的名字就不一樣,就支持了重載。
七、C++的引用
?7.1 、引用概念
?????????引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開(kāi)辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。
? ? ? ? 就是類(lèi)似于有些和正品耐克鞋質(zhì)量一樣好的莆田鞋,他們之間的價(jià)格可能差了好幾倍,但是他們的本質(zhì)是一樣的。
代碼+監(jiān)視示例:
?7.2、 引用特性
1. 引用在定義時(shí)必須初始化
2. 一個(gè)變量可以有多個(gè)引用?
3. 引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體
賦值操作執(zhí)行時(shí),比如說(shuō)是上面的e賦值給b,編譯器會(huì)給e產(chǎn)生一個(gè)臨時(shí)變量,再把臨時(shí)變量賦值給b,臨時(shí)變量具有常性權(quán)限縮小,所以+const?
比如:
示例1:
int main() {int a = 10;int& b = a;//不變//取別名原則:對(duì)原引用變量,權(quán)限只能縮小,不能放大const int x = 20;//const是可讀但不可改寫(xiě)(讀寫(xiě)權(quán)限)//int& y = x; //權(quán)限放大了const int& y = x;int c = 30;const int& d = c;//權(quán)限的縮小return 0; }示例2:
int main() {int a = 10;int& b = a;const int& c = 20;//在傳參過(guò)程取別名,才是它更多的作用//C++允許相似類(lèi)型隱式轉(zhuǎn)換,會(huì)發(fā)生截?cái)嗷蛘呤钦翁嵘齞ouble d = 2.2;const int& e = d;//e是臨時(shí)變量的地址,不是d的地址retuen 0; }7.3、?使用場(chǎng)景
1、做參數(shù)
void Swap(int& left, int& right) {int temp = left;left = right;right = temp; }?2. 做返回值
int& Count() {static int n = 0;n++;// ...return n; }?注意:
????????如果函數(shù)返回時(shí),出了函數(shù)作用域,如果返回對(duì)象還未還給系統(tǒng),則可以使用引用返回,如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。
7.4、傳值、傳引用效率比較
????????以值作為參數(shù)或者返回值類(lèi)型,在傳參和返回期間,函數(shù)不會(huì)直接傳遞實(shí)參或者將變量本身直接返回,而是 傳遞實(shí)參或者返回變量的一份臨時(shí)的拷貝,因此用值作為參數(shù)或者返回值類(lèi)型,效率是非常低下的,尤其是當(dāng)參數(shù)或者返回值類(lèi)型非常大時(shí),效率就更低。
測(cè)試引用傳參的效率、傳值、指針傳參效率的區(qū)別的函數(shù)
#include <time.h> struct A{ int a[10000]; }; void TestFunc1(A aa){} void TestFunc2(A& aa){} void TestFunc3(A* paa){} 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();size_t begin3 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc3(&a);size_t end3 = clock();// 分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;cout << "TestFunc3(A*)-time:" << end3 - begin3 << endl; }在我的電腦下測(cè)試結(jié)果
順帶提一下引用和指針的區(qū)別:底層的角度,指針和引用是一樣的,因?yàn)橐玫讓泳褪侵羔?/strong>
?為啥傳值會(huì)更慢?
傳值調(diào)用會(huì)產(chǎn)生一個(gè)臨時(shí)變量,也就是圖中的方塊,所以效率更低
?7.5、引用和指針的不同點(diǎn):
1. 引用在定義時(shí)必須初始化,指針沒(méi)有要求
2. 引用在初始化時(shí)引用一個(gè)實(shí)體后,就不能再引用其他實(shí)體,而指針可以在任何時(shí)候指向任何一個(gè)同類(lèi)型 實(shí)體
3. 沒(méi)有NULL引用,但有NULL指針
4. 在sizeof中含義不同:引用結(jié)果為引用類(lèi)型的大小,但指針始終是地址空間所占字節(jié)個(gè)數(shù)(32位平臺(tái)下占 4個(gè)字節(jié))
5. 引用自加即引用的實(shí)體增加1,指針自加即指針向后偏移一個(gè)類(lèi)型的大小
6. 有多級(jí)指針,但是沒(méi)有多級(jí)引用
7. 訪問(wèn)實(shí)體方式不同,指針需要顯式解引用,引用編譯器自己處理
8. 引用比指針使用起來(lái)相對(duì)更安全
八、內(nèi)聯(lián)函數(shù)
8.1、內(nèi)聯(lián)函數(shù)的概念
????????以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開(kāi),沒(méi)有函數(shù)壓棧的開(kāi)銷(xiāo), 內(nèi)聯(lián)函數(shù)提升程序運(yùn)行的效率。
8.2、內(nèi)聯(lián)函數(shù)的特性
????????1. inline是一種以空間換時(shí)間的做法,省去調(diào)用函數(shù)額開(kāi)銷(xiāo)。所以代碼很長(zhǎng)或者有循環(huán)/遞歸的函數(shù)不適宜 使用作為內(nèi)聯(lián)函數(shù)。
????????2. inline對(duì)于編譯器而言只是一個(gè)建議,編譯器會(huì)自動(dòng)優(yōu)化,如果定義為inline的函數(shù)體內(nèi)有循環(huán)/遞歸等 等,編譯器優(yōu)化時(shí)會(huì)忽略掉內(nèi)聯(lián)。
????????3. inline不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。因?yàn)閕nline被展開(kāi),就沒(méi)有函數(shù)地址了,鏈接就會(huì) 找不到。
探究:為什么C++要寫(xiě)出內(nèi)聯(lián)函數(shù)?
用C語(yǔ)言實(shí)現(xiàn)一個(gè)加法的宏
#define ADD(x, y)((x) + (y))?宏的優(yōu)缺點(diǎn):
優(yōu)點(diǎn): 1.增強(qiáng)代碼的復(fù)用性。 2.提高性能。 缺點(diǎn): 1.不方便調(diào)試宏。(因?yàn)轭A(yù)編譯階段進(jìn)行了替換) 2.導(dǎo)致代碼可讀性差,可維護(hù)性差,容易誤用。 3.沒(méi)有類(lèi)型安全的檢查 。
使用內(nèi)聯(lián)寫(xiě)一個(gè)加法函數(shù)
inline int Add(int x, int y) {int z = x + y;return z; }?內(nèi)聯(lián)函數(shù)的優(yōu)點(diǎn):
????????inline: 1、debug版本下支持調(diào)試 2、不容易寫(xiě)錯(cuò),就是普通函數(shù)的寫(xiě)法
所以?xún)?nèi)聯(lián)函數(shù)是替換宏的一個(gè)好辦法。
總結(jié)
? ? ? ? 本文寫(xiě)了約7000字,比較詳細(xì)地向大家介紹了什么是C++以及C++發(fā)展歷史,?還向大家講述了C++關(guān)鍵字、命名空間等知識(shí),希望大家在看完后能夠有所收獲,感謝大家的支持!
總結(jié)
以上是生活随笔為你收集整理的【C++】 C++入门和基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 最新emoji表情代码大全_8张最新创意
- 下一篇: s3c2440移植MQTT