文章目錄
知識點 0:命名空間
爲了避免工作中模塊化工作所造成的函數名,變量名的命名衝突,引入命名空間概念,在此命名空間內的所有內容生命週期都只侷限於該命名空間之中,不會和其他變量或函數造成同名衝突。
namespace Zone {//Zone 爲命名空間的名稱,相同命名空間會自動合成同一個空間(同名空間中不允許出現重複定義)
//可以定義變量,函數等
int a;
namespace Zone1{
//可以嵌套定義
int b;
}
}
最爲推薦的命名空間元素使用方式:Zone ::a
或Zone::Zone1::b
知識點 1:標準輸出輸入
編寫C++程序標準輸入輸出所需要包含的頭文件
#include <iostream>
using namespace std;
//標準輸入輸出格式
輸入:cin>>b>>a;
輸出:cout<<a<<b<<endl; (endl爲換行符)
//支持連續輸入輸出
其中字符串和非字符串輸出是有本質區別的:非字符串指針輸出首地址,字符串指針輸出字符串內容
int a = 10 ;
char* p = "1234";
int* pa = &a;
std::cout << pa << std::endl; //非字符串指針輸出地址
std::cout << p << std::endl; //字符串指針輸出內容
知識點 2:缺省參數
如果沒有指定實參時,採用默認參數值的一種。
- 全缺省參數
void TestFunc(int a = 10, int b = 20, int c = 30)
- 半缺省參數
void TestFunc(int a, int b = 10, int c = 20)
因爲參數的接受順序時從左向右,因此半缺省參數必須從右往左依次給出,不能存在間隔;缺省的參數不能在函數和定義中重複出現,編譯器無法確定到底使用那個缺省值。
知識點 3:函數重載
同名函數的形參列表(參數個數,類型,順序)必須不同,僅僅是返回值不同不能夠構成函數重載。
int Add(int a = 1, int b = 2);
float Add(float a, float b);
int Add(int a, int b ,int c);
int Add(char a, char b) ;
int Add(int a, char b);
int Add(char a, int b)
讓編譯器按照C語言編譯規則來進行編譯
extern "C" {
int sub(int a, int b);
int mul(int a, int b);
}
- 爲何C++支持函數重載,而C語言不支持函數重載
- C語言編譯後,函數名修飾沒發生任何改變,因此不論參數,類型發生任何改變,都是同一個函數,不會發生重載。
- C++編譯時,編譯器會講函數參數類型等具體信息添加到函數名中。
- 換言之,C語言編譯後同名函數無法進行區分,而C++時通過函數修飾規則來進行區分,即使同名函數調用時底層函數也是不同。
- C和C++編譯的本質
知識點 4:引用
對已經存在的變量取一個別名,稱之爲引用(不會開闢內存空間,使用同一塊內存空間,大小名的區別)——引用的效率是要高於正常傳參的效率的。
- 標準化引用
int a = 10;
int& ra=a;//引用 引用必須初始化
// int& ra; 這是錯誤的;
ra =100;// 賦值 引用定義後不會改變實體的指向,因此會將原有內容全部改爲100
- const類型的引用
const int a= 10;
const int& ra =a;//const類型必須用const類型來進行引用 且不能夠被修改
int& rb =10; //這是錯誤的,b爲常量不能進行引用
const int& rb =10;
double d =2.0 ;
double& rb =d;//引用類型必須和實體類型同類
int c=d;
const int& rd = d;//隱式類型轉換,所生成的是一個臨時整型變量,因此rd指向臨時變量,具備常量特性不能夠修改
- 引用作返回值
引用作返回值時,必須注意的是返回變量的生命週期一定要大於函數的生命週期
int& Add2(int a) {//函數結束,a已進行銷燬,無法進行引用
return ++a;
}
void Test3() {
int a = 0;
int& d= Add2(a);//無法完成 ,因爲a在函數結束時候已經銷燬,因此出現訪問越界的問題
cout << d << endl;
}
引用和指針的區別:
語法上:引用是一個別名,沒有獨立的空間,和其引用實體共用同一塊空間
底層實現上:是有空間的,因爲引用按照指針方式來進行實現的
- 引用在定義時必須初始化,而指針沒有要求
- 引用再引用一個實體後,就不能在引用其他實體,而指針可以隨意指向任何一個同類型實體
- 沒有NULL引用,但有NULL指針
- sizeof含義不同,引用結果爲引用類型大小,而指針始終時地址空間所佔字節個數
- 引用自加即引用實體增加1,指針自加則表示指針向後偏移一個類型大小
- 存在多級指針,但沒多級引用
- 訪問實體方式不同,指針需要顯示解引用,引用編輯器會自己處理
- 引用比指針用起來更加的安全
知識點 5:內聯函數
編譯時會將函數指令展開,不產生站真的開銷,有效的提高代碼的效率,可以代替宏函數的使用。(當然,內聯函數只是一個建議,編譯器會根據程序的實際情況來進行判斷,如果代碼簡單則直接展開,否則會按照函數運行)
inline int Add(int a, int b)
{
return a + b;
}
知識點 6:auto自動類型
自動進行類型推導,相當於類型的佔位符,不代表任何具體類型的存在,具體的類型會在編譯時進行推導得到。
auto b = 2;
auto f = 3.0;
auto c = 'a';
auto d = 'a' + 'b';
cout << typeid(b).name() << endl;//整型
cout << typeid(f).name() << endl;//浮點型
cout << typeid(c).name() << endl;//字符型
cout << typeid(d).name() << endl;//整型也可能是字符型
- auto定義的變量必須初始化,且可以定義多個定義
- 定義多個變量,每一個表達式類型要一致
- 對於長類型變量定義使用更加簡單
- 定義引用類型必須
auto& ra =b;
- 函數參數類型和數組不能夠使用auto
知識點 7:範圍for
對於數據範圍確定的數據來說,可以使用範圍for來進行(範圍不確定一定不能使用範圍for)
int array[]={1,2,3,4,5,6};
for(auto e: array)
cout<<e<<" ";
知識點 7+:nullptr
(NULL擁有二義性,指針空指和整型0)NULL在編譯時會被默認爲整型0,而不是我們所謂的空指針;而nullptr時指針空指,建議用nullptr表示指針控制,意義更加的明確。
int* p=NULL; 等價於 int* p=0;
nullptr類型: nullptr_t
nullptr可以隱式轉換成任意指針類型(內置和自定義)
nullptr: 指針空值, 建議用nullptr表示指針空值,意義明確