目錄
1、C++入門
1)C++關鍵字
2)命名空間
3)C++中的輸入輸出
4)缺省參數
5)函數重載
6)引用
引用和指針的不同點:
7)auto關鍵字
8)內聯函數
9)指針空值nullptr
1、C++入門
主要介紹C++中新增的一些C語言中沒有的內容作為C語言的補充,以便于更加方便地進行編程實現,以及為后期的C++的學習打下基礎
1)C++關鍵字
C++中有98個關鍵字,而其中32個是C語言中的,我認為對于這些關鍵字不需要特別地去進行記憶,只需要先做些大概的了解,在后續學習和使用的過程中去逐步地加深理解。
2)命名空間
由于在C語言中時常會出現命名沖突的問題,比如變量名和庫沖突、變量名之間的沖突,這會帶來很多的不便,于是在C++中就進行了一些優化,使用namespace的關鍵字,也就是命名空間來設定一個域,實現變量之間的隔離,以此解決沖突問題。幾種常見的域:類域、命名空間域、局部域、全局域
//命名空間的定義
namespace A //A為命名空間的名稱
{int a; //命名空間中可以定義變量int add(int x,int y) //命名空間中也可以定義函數{return x+y;}
}int a=0; //這是一個全局變量//命名空間可以進行嵌套使用
namespace A
{int a=1; namespace B{int a=2;}
}
如果有多個相同名稱的命名空間會被編譯器合并,一個命名空間就定義了一個新的作用域,命名空間中所有內容都局限于該命名空間中。在使用時,可以通過作用域限定符來進行訪問命名空間中的部分成員,也可以使用using來進行展開命名空間中的內容進行使用,還可以通過using namespace來展開整個命名空間域,此時命名空間中的所有成員都可以被使用
namespace A
{int a=1;
}using A::a; //使用using來展開命名空間中需要的成員,展開的內容就成為了全局域using namespace A; //使用using namespace來展開命名空間域,可以訪問命名空間內的所有內容int main()
{A::a=10; //使用作用域限定符來進行使用命名空間中的成員printf("%d",A::a);
}
3)C++中的輸入輸出
<<為C++中的流插入運算符,可以實現輸出
>>為C++中的流提取運算符,可以實現輸入
#include<iostream>
using namespace std;
int main()
{int x = 0;int i = 0;int j = 0;cin >> j; //輸入cin >> x>>i; //可以連續輸入,輸入值將按照順序從左向右放在相應的變量中cout << j << endl; //輸出,endl為換行cout << "hello world" << endl<<x <<" " << i; //可以連續輸出
}
當然由于C++是兼容C語言的,因此在C++中依然可以使用scanf和printf的函數實現輸入輸出,不過C語言的這兩個輸入輸出函數會對輸入輸出的內容進行格式限制,即需要使用%d %c等限定類型,而C++中的cout和cin則并沒有限制,這也方便了后期自定義類型的使用。
4)缺省參數
缺省參數使用在函數聲明或定義時,為函數的參數設定的一個默認值,當調用函數而未傳入參數時就會使用缺省參數,當傳入了參數時,缺省參數將不會被使用,也就是說缺少參數擔任了一個備胎的角色
缺省可以是全缺省也可以是半缺省(即部分變量有缺省值,部分沒有,但半缺省必須從右往左依次給出缺省值,不可以間隔給出,也不可以給左不給右)
#include<iostream>
using namespace std;
void Print(int x=1 ,int y=2,int z=3) //全缺省
{cout << x << " " << y << " "<<z<<" " << endl;
}
void Print1(int x , int y , int z = 10) //半缺省
{cout << x << " " << y << " " << z << " " << endl;
}/*void Print(int x=1 ,int y,int z)
{cout << x << " " << y << " "<<z<<" " << endl;
}
void Print1(int x , int y=1 , int z)
{cout << x << " " << y << " " << z << " " << endl;
}
這兩種缺省方式都是錯誤的
*/
int main()
{Print(); //全部使用缺省值Print(4); //為給參數的部分使用缺省值Print1(99,0); //使用缺省值Print(10,12,16); //不使用缺省值,使用傳入的參數}
注意:缺省參數只能在函數聲明時出現,或者函數定義時出現(二者之一均正確),不可以在聲明和定義中同時出現
5)函數重載
在C++中的同一作用域中可以聲明和定義幾個功能類似的同名函數,這些函數的形參列表(參數類型、參數個數、參數順序)不同,但功能類似且函數名相同,那么就構成函數重載
#include<iosteam>
using namespace std;
//1.參數類型不同
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;
}//2.參數個數不同
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}//3.參數類型順序不同
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()
{cout << Add(1,2) << endl;cout << Add(1.1, 2.2) << endl;f();f(10);f(10,'a');f('a',10);return 0;
}
如果兩個函數名稱相同、形參相同但返回值不同,則不構成函數重載
那么為什么重載在C語言中不能實現,而在C++中可以實現呢,這是因為在鏈接的過程中,C語言是通過函數名來查找函數地址的,因此不允許有同名的函數,而C++查找時并不是單純通過函數名來查找,而是使用了函數名修飾規則,使用參數來進行修飾,同時返回值并沒有被用于修飾規則中
6)引用
C語言中的指針的使用較為復雜且易錯,因此C++中采用了一種新的方式,即為引用,引用也就是取別名,引用并沒有開辟新的空間來存放變量,而是對已經存在的變量取了一個新的名字,因此引用變量與原變量公用一塊內存空間,引用不可以改變指向。
比如:西游記中的猴子,可以叫他悟空,也可以叫他齊天大圣
int main()
{int a = 6;int& b = a;//注意:引用類型必須和引用實體是同種類型的cout << b << endl; //打印出b的值和a的值一樣b++;cout << a; //由于a、b使用的是同一塊空間,因此++時會同時++}
引用的特性:1、引用在定義時必須初始化 2、一個變量可以有多個引用 3、引用一旦引用一個實體,再不能引用其他實體
#include<iostream>
using namespace std;
int main()
{//一個變量可以有多個引用int a=0;int& b=0;int& c=b;//引用在定義時必須初始化//int& d; 報錯//引用一旦引用一個實體,再不能引用其他實體int x=10;c=x;//x的值賦值給c,c依舊是a/b對象別名
}
引用的使用場景:1、作為參數(基本任何場景都可以用引用傳參)2、作為返回值(要謹慎,如果函數調用結束后,引用的變量已經被銷毀,那么該引用相當于野指針,不可以引用返回,除非是靜態變量等不被銷毀的情況下才可以使用)
引用和指針的不同點:
1、引用概念上定義一個變量的別名,指針存儲一個變量地址
2、引用在定義時必須初始化,指針沒有要求
3、引用在初始化時引用一個實體后,就不能再引用其他實體,而指針可以在任何時候指向任何一個同類型實體
4、沒有NULL引用,但有NULL指針
5、在sizeof中含義不同:引用結果為引用類型的大小,但指針始終是地址空間所占字節個數(32位平臺下占4個字節)
6、引用自加即引用的實體增加1,指針自加即指針向后偏移一個類型的大小
7、有多級指針,但沒有多級引用
8、訪問實體方式不同,指針需要顯式解引用,引用編譯器自己處理
9、引用比指針使用起來相對更安全
7)auto關鍵字
auto會根據表達式的類型自動推導出類型,當類型很長時使用auto會比較方便
#include<iostream>
using namespace std;int main()
{int a=0;int b=a;auto c=a;//根據右邊的表達式自動推導c的類型auto d=1+1.11;//根據右邊的表達式自動推導d的類型cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;//打印變量的類型
}
注意:auto不能作為函數的參數,也不能直接用來聲明
auto可以用于for循環,會比較方便,但是for循環的范圍一定要是確定的
#include<iostream>
using namespace std;int main()
{int a[]={1,2,3,4,5,6,7,8,9,10};//適用于數組//范圍for 語法糖(訪問數組)//依次取數組中數據賦值給e//自動迭代,自動判斷結束for(auto e : arr){cout << e << " ";}cout << endl;//修改數據for(auto& e : arr){e *=2;}for(auto e :arr){cout << e << " ";}cout << endl;
}
8)內聯函數
在進行函數調用時會有一些消耗,比如建立函數棧幀這些,C語言中可以通過使用宏函數來解決,但是宏函數比較容易出錯,因此C++中采用了內聯函數來解決問題,在調用的函數返回值之前加上關鍵字inline,即成為內聯函數,內聯函數會在函數調用的地方展開,則沒有函數調用了,所以內聯函數不需要建立棧幀,不復雜,不容易出錯,可讀性強,可以調試
#include<iostream>
using namespace std;
//內聯函數
inline int Add(int x,int y)
{return (x+y)*10;
}int main()
{for(int i=0;i<10000;i++){cout << Add(i,i+1) << endl;}return 0;
}
但是宏函數和內聯函數都只適用于短小的頻繁調用的函數,如果用于較長的函數則會導致代碼膨脹,因此當在編寫代碼時使用了inline只會作為一種建議,最終運行時將會由編譯器決定是否將函數設為內聯函數
注意:inline函數不能聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址了,鏈接就會找不到
9)指針空值nullptr
在C語言中我們通常認為NULL就為空指針,但是NULL其實是一個宏定義,NULL就為0
#include<iostream>
using namespace std;
void f(int)
{cout << "f(int)" << endl;
}void f(int*)
{cout << "f(int*)" << endl;
}int main()
{f(0);f(NULL);
}
因此當我們在運行以上代碼時會發現只調用了f(int)函數,由于NULL被當做是0而無法調用f(int*)這一函數,為了解決這一問題,在c++中使用nullptr來表示空指針