前沿:
c++作為目前比較的流行的語言之一,在就業上也是運用比較廣泛的語言之一,并且經過這麼多年的曆練久經不衰,是以說選擇學c++是一個不錯的選擇^_^,前面看到一個段子,如何在21天精通c++,我動态裡有這張圖檔,一個努力的程式員經過幾年的磨練也隻能說是熟悉c++,對于語言的學習并不可能有速成班,都是不斷的積累,c++也是如此,但相比較c語言,c++的文法特性繁瑣複雜,知識點比較瑣碎,它是對c語言一些缺陷的完善,并且保留c語言的所有特性,也就是c語言能用的在c++中也能實作,在學習過程中,一定要做好總結和思維導圖的建構,把每個知識進行良好的串聯在一起,才能熟悉的運用它,而本篇部落格也隻是初步的認識一下c++,隻能讓你淺淺的進入新手村。
思維導圖:
目錄
一、命名空間:
1.1命名空間存在的意義:
1.2命名空間的定義:
1.3命名空間的使用:
二、c++的輸入與輸出:
2.1第一個c++函數:
2.2c++的輸入與輸出:
三、預設參數:
3.1預設參數的定義:
3.2省參數的分類:
四、函數重載:
4.1函數重載的意義:
4.2函數重載的概念:
4.3函數重載的列舉:
五、引用:
5.1引用的概念:
5.2引用的特性:
5.3引用的應用:
5.5引用和指針的差別:
六、内聯函數:
6.1内斂函數存在的意義:
6.2内斂函數的定義:
6.3内斂函數特性:
總結:
一、命名空間:
1.1命名空間存在的意義:
1.1.1要知道c++是對c語言缺點的完善,而在c語言中我們是知道,定義變量、函數名或者全域名是不能相同的,否則會産生沖突,但要知道這都是大量存在的,就像一個名字也有很多重名,一個項目,每個人負責不同的子產品,也避免不了名字相同(因為我不知道你也用了這個名字),在c語言中就會産生沖突,而且在全域中也可能和庫函數中名字相同例如:
#include<stdio.h>
#include<stdlib.h>
int rand=10;//編譯後後報錯:error C2365: “rand”: 重定義;以前的定義是“函數
int main()
{
printf("%d\n",rand);
return 0;
}
這裡編譯錯誤在c語言中就是沒辦法避免的,是以c語言編譯就要避免和c語言庫裡函數名相同,這是很麻煩的,要知道我們并不能知道所有庫函數,而c++命名空間的存在就解決了這個問題。
1.2命名空間的定義:
1.2.1命名空間的定義要用到一個關鍵字就是namespace加命名空間的名字,然後接一個{ },裡面就是命名空間的成員。
//這我定義的名字為xiaoma
namespace xiaoma
{
//可以定義變量也可以定義函數
int rand =10;
int Add(int x,int y)
{
return x+y;
}
//同時也可以進行嵌套
namespace hello{
//嵌套在命名空間xiaoma的命名空間hello
//不同命名空間裡的名字可以相同
int rand=20;
int Add(int x,int y)
{
return x+Y;
}
}
}
1.3命名空間的使用:
1.3.1命名空間中的成員并不能直接使用,有三種形式使用方式:
<1>加命名空間名稱以及作用域符号:
namespace xiaoma
{
int a=10;
int b=20;
}
int main()
{
// printf("%d\n",a) 這種是錯誤的不能直接使用
printf("%d\n",xiaoma::a);
printf("%d\n",xiaoma::b);
return 0;
}
<2>使用using将命名空間某個成員引入:
namespace xiaoma
{
int a=10;
int b=20;
}
usinng xiaoma::a;
int main()
{
// printf("%d\n",a) 這種是錯誤的不能直接使用
printf("%d\n",a); //這個已經被引入了是以可以直接用
printf("%d\n",xiaoma::b);
return 0;
}
<3>使用using namespace命名空間的引入
namespace xiaoma
{
int a=10;
int b=20;
}
usinng namespace xiaoma;
int main()
{
printf("%d\n",a);
printf("%d\n",b);
return 0;
}
二、c++的輸入與輸出:
2.1第一個c++函數:
2.1.1就像學習c語言一樣,我們學習c++也們也來寫第一個c++函數。
#include<iostream>
using namespace std;
int main()
{
cout<<"Hello World"<<endl; //endl表示換行的意思
return 0;
}
2.2c++的輸入與輸出:
#include<iostream>
using namespace std;
int main()
{
int a;
double b;
char c;
//可以自動識别變量類型
cin>>a;
cin>>b>>c;
cout<<a<<endl;
cout<<b<<' '<<c<<endl;
return 0;
}
2.2.1cout(輸出)和cin (輸入)的使用必須包含頭檔案<iostream>和以及按命名空間使用方法使用std.
2.2.2<<是流插入運算符,>>是流提取運算符。 2.2.3std是C++标準庫的命名空間,怎麼了解呢?他就好比一個圍牆,把标準庫全放放在裡面,而我們要通路,就需要透過圍牆來進行通路。
三、預設參數:
3.1預設參數的定義:
3.1.1預設參數是聲明或定義函數時為函數的參數指定一個預設值。在調用該函數時,如果沒有指定實,參則采用該形參的預設值,否則使用指定的實參。
#include<iostream>
using namespace std;
int Add(int x=10,int y=20)
{
return x+y;
}
int main()
{
int ret1=Add(); //不穿參數,使用形參預設值
cout<<ret1<<endl;
int ret2=Add(1,2) //穿參數,使用指定實參
cout<<ret2<<endl;
return 0;
}
3.2省參數的分類:
3.2.1全預設參數:
#include<iostream>
using namespace std;
int Add(int x=10,int y=20,int z=30)
{
return x+y+z;
}
int main()
{
int ret1=Add(); //可以不傳參數
int ret2=Add(1); //可以傳一個參數
int ret3=Add(1,2); //可以傳兩個參數
int ret4=Add(1,2,3); //可以傳三個參數
//但不能像Add(,2,3)或者這樣Add(1,,3)傳參,必須是從左到右連續滴傳參。
cout<<ret1<<endl<<ret2<<endl<<ret3<<endl<<ret4<<endl;
}
3.2.2半省參數:
#include<iostream>
using namespace std;
int Add(int x,int y=20,int z=30)
{
return x+y+z;
}
//半省參數必須從右向左依次指派
int Add1(int x,int y,int z=30)
{
return x+y+z;
}
//上面兩種都是可以的
//但不能中間間隔例如:int Add(int x=10,int y,int z=30)
//或者這樣也是不行的 int Add(int x=10,int y,int z)
int main()
{
int ret1=Add(1,2,3);//可以
int ret2=Add(1,2);//可以
int ret3=Add(1);//可以
// int ret4=Add(); 不可以的x需要傳參
同樣滴
int ret5 =Add1(1,2,3);//可以
int ret6=Add(1,2);//可以
// int ret7=Add(1); 不可以因為y沒有傳參
//半預設參數是要指派的
return 0;
}
四、函數重載:
4.1函數重載的意義:
4.1.1在日常生活中我們也經常遇到一個詞表達不同的意思,例如中國的體育項目的兩大極端:
乒乓球和足球一個是“誰也赢不了”另一個也是“誰也赢不了”相同的詞表達這不同的意思,c++中的重載也在此展現來。
4.2函數重載的概念:
4.2.1是函數的一種特殊情況,C++允許在同一作用域中聲明幾個功能類似的同名函數,這
些同名函數的形參清單(參數個數或類型或類型順序)不同,常用來處理實作功能類似資料類型 不同的問題。
4.3函數重載的列舉:
#include<iostream>
using namespace std;
int Add(int x,int y,int z)
{
return x+y+z;
}
//參數個數不同
int Add(int x,int y)
{
return x+y;
}
//參數類型不同
double Add(double x,double y)
{
return x+y;
}
//參數順序不同
double Add(int x,double y)
{
return x+y;
}
double Add(double y, int x)
{
return x+y;
}
int main()
{
int ret =Add(1,2,3);
int ret1=Add(1,2);
double ret2=Add(1.2,2.2);
double ret3=Add(1,1.2);
double ret4=Add(1.2,1); //函數重載的作用就是一個函數可以實行多種功能
cout<<ret<<endl<<ret1<<endl<<ret2<<endl<<ret3<<endl<<ret4<<endl;
return 0;
}
五、引用:
5.1引用的概念:
5.1.1引用比較好了解啦,就是給你原有的變量去了一個别名,例如在生活中你的外号,就像叫我小馬一樣都是别名的意思,編譯器不會給引用變量開辟新的記憶體,他和他引用的變量公用同一個記憶體空間。
#include<iostream>
using namespace std;
int main()
{
int a=10;
int& ra=a;
printf("%p\n",&a); //列印a的位址
printf("%p\n",&ra); //列印ra的位址 兩個位址是相同的
return 0;
}
5.2引用的特性:
<1>引用變量必須初始化。 就像你給一個人起小名要有對象呀
<2>一個變量可以有多個引用。 一個人可以有多個外号什麼的
<3>引用一旦引用一個實體,再也不能引用其他實體。
#include<iostream>
using namespace std;
int main()
{
int a=10;
int&ra=a; //這是引用的初始化
// int&ra; //這裡沒有初始化是不正确的。
int& rb=a; //一個變量可以有多個引用
return 0;
}
5.3引用的應用:
5.3.1引用做參數:
通過引用的概念我們可以知道引用是和他的引用變量用同一個位址,是以改變引用就是改變他所引用的變量,就像誇小馬文章寫的好不就是在誇我嗎^ _ ^。
#include<iostream>
using namespace std;
void swap(int& x,int& y)
{
int tmp=0;
tmp=x;
x=y;
y=tmp;
}
int main()
{
int x=10;
int y=20;
swap(x,y);
cout<<x<<' '<<y<<endl;
return 0;
}
5.3.2引用做傳回值:
#include<iostream>
using namespace std;
int& Add(int x,int y)
{
static int ret=x+y; //想想這裡為什麼用static
return ret;
}
int main()
{
int ret=Add(1,2);
cout<<ret<<endl;
return 0;
}
在這裡我們想一下為什麼要用static 要是不用static的後果是什麼呢? 在我們講函數棧幀的建立和銷毀的時候已經知道,局部變量是儲存在棧區的,而棧區是随着函數調用結束後是會被銷毀的, 但引用是和引用對象一個位址的,static是把局部變量從棧區存放到靜态區,這樣随着函數的調用結束後不會被銷毀,是以傳回的時候還能夠找到,要是不用static當傳回去尋找的時候是找到的就會是随機值。就好比你住個酒店,而當你退房了之後,發現你的包裹沒有拿,而當你傳回去的時候,你就無法确定你的包裹還在,他可能還在就是沒有被收拾,但有可能你住的酒店已經被其他使用者住給扔掉了,這都是有可能的,而static就是把包放在一個儲存的東西的地方,你再去這個地方拿就行了。
5.5引用和指針的差別:
5.5.1引用就是引用對象的一個别名,而指針是變量的位址/
5.5.2引用必須初始化,而位址不需要初始化。
5.5.3引用在初始化一個引用對象後就不能在引用其他變量了,而指針确可以在任何時候指向同類型的位址。
5.5.4引用自身加一是引用對象加一,而指針加一則是位址加一。
5.5.5指針有多級指針,而引用沒有
六、内聯函數:
6.1内斂函數存在的意義:
在c語言中調用一個函數要經過棧幀的建立和銷毀,而當一個函數調用次數過多的時候就會降低程式運作的效率。這裡的解決辦法是什麼呢?在c語言中有一個解決的方法就是宏函數。想必大家也忘了宏函數的寫法了,這裡我寫一個宏函數的代碼。
#include<iostream>
using namespace std;
#define Add(x,y) ((x)+(y))
int main()
{
int ret=Add(1,2);
cout<<ret<<endl;
return 0;
}
為什麼宏函數解決了效率呢,要知道一個程式運作的完整運作,是有預處理,編譯,彙編,連結四個過程的,而宏函數是在預處理已經完成了。但宏函數已經解決了c棧幀建立和銷毀的缺點,為什c++還會建立一個内斂函數呢?要知道雖然宏函數解決了效率問題,但它本身也有自身的缺點,我們可以看出宏函數還是很容易寫錯的,我這個是比較簡單的,要是複雜一點就是很容易就寫錯的,而宏函數因為在預處理就已經結束了,是以是沒有辦法調試的,并且他也沒有類型安全的檢查,是以c++就用内斂函數來解決這個問題。
6.2内斂函數的定義:
6.2.1以inline修飾的函數叫做内聯函數,編譯時C++編譯器會在調用内聯函數的地方展開,沒有函數調 用建立棧幀的開銷,内聯函數提升程式運作的效率。
#include<iostream>
using namespace std;
inline int Add(int x,int y)
{
return x+y;
}
int main()
{
int ret =Add(1,2);
cout<<ret<<endl;
return 0;
}
内斂函數和普通函數功能相同就是在函數inline同時也具有了宏函數的一些功能就是不參與編譯,在預處理就已經完成了。
6.3内斂函數特性:
6.3.1 inline是一種以空間換時間的做法,如果編譯器将函數當成内聯函數處理,在編譯階段,會 用函數體替換函數調用,缺陷:可能會使目标檔案變大,優勢:少了調用開銷,提高程式運 行效率。 6.3.2 inline對于編譯器而言隻是一個建議,不同編譯器關于inline實作機制可能不同,一般建 議:将函數規模較小(即函數不是很長,具體沒有準确的說法,取決于編譯器内部實作)、不 是遞歸、且頻繁調用的函數采用inline修飾,否則編譯器會忽略inline特性。 6.3.3 inline不建議聲明和定義分離,分離會導緻連結錯誤。因為inline被展開,就沒有函數位址 了,連結就會找不到
總結:
對于這篇文章講的隻是讓我們初步的了解認識c++語言,就相當于進入一個新手村才剛剛開始,而c++的脊髓還在後面,就是c++引入類的概念,使c語言的面對過程變為了面對對象,這才是c++魅力所在,而這篇文章讓我們可能看的懂一點點簡單的c++文章,但淺淺的總結小馬也寫了5000+字數,對于一些東西還是棧幀的了解深度,是以對于棧幀不了解的夥伴一定要認真看看棧幀,我前篇的文章哈哈哈哈,還有一定要注重思維導圖和總結!!
^_^最後小馬碼文不易,如果覺得文章有幫助的可以點贊關注,希望我們一同學習,共同進步!!!