天天看點

c++---初始函數重載、預設參數、命名空間等

  • c++的關鍵字
  • 命名空間
  • c++自己的輸入輸出
  • 預設參數
  • 函數重載
  • 引用
  • 内聯函數r
  1. c++關鍵字

    c++的關鍵字包括了我們的asm、do、if、return、try、continue、auto、double、inline、short、typedef、for、bool、dynamic_case、int、signed、typeid、public、break、else、long、sizeof、typename、throw、case、enum、mutable、static、union、wchar_t、catch、explicit、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、protected、this、volatile、while、delete、goto、reinterpret_cast。我們将在學習c++過程中慢慢接觸到我們的關鍵字。c++在不斷的更新,可能以後我們的關鍵字會改變,但是萬變不離其宗,大多數的關鍵字還是會保留的。

  2. 命名空間

    命名空間就是用來解決命名沖突的,在一個大項目中,可能自己和别人定義的變量名或者函數名重複的時候就需要使用命名空間。定義命名空間需要使用到那麼誰趴廁關鍵字,後面跟命名空間的名字,然後使用一對{}。在{}中就是我們定義的變量那個或者函數。

    命名空間需要注意的點

  • 命名空間中的内容可以是函數,也可以是變量
  • 命名空間可以嵌套定義
  • 同一個工程中存在多個相同命名空間的時候,編譯器會合成是以的命名空間,隻使用一個來包含所有的命名空間中的内容
namespace N1{
	int a;
	int b;
	int add(int x,int y){
		return x+y;
	}
}
namespace N2{
	int a;
	namespace N3{
		int y;
	}
}
namespace N1{
	int c;
}
           

在最後一個N1的命名空間的時候我們相當于下面的

namespace N1{
	int a;
	int b;
	int c;
	int add(int x,int y){
		return x+y;
	}
}
           

我們定義好了一個命名空間又怎樣去使用它呢,我們使用命名空間的方法有三種

  • 命名空間名稱+作用域限定符
  • 使用using将命名空間中成員引入
  • 使用using namespace 命名空間名稱引入

    我們推薦前兩種,因為在最後一種全部展開的時候是最容易引起命名沖突的。

  1. c++輸入輸出

    c++有自己的輸入輸出,在c++中我們使用cin和cout來進行資料的輸入和輸出,使用cout标準輸出和cin标準輸入時,需要包含我們的頭檔案以及我們的std标準命名空間

#include <iostream>
using namespace std;
int main(){
	int i;
	cin >> i;
	cout << "hello world" << endl;
	return 0;
}
           

可能你會想問我們的>><<是幹什麼用的,這不是我們c語言中的左移和右移。他是指向我們的資料流向的,endl是我們c++中的換行符号,就與我們c語言中的\n是一樣的。

  1. 預設參數

    在c語言中我們的函數在定義的時候我們隻能給出我們函數參數的類型,并不能給我們的參數指派。在我們的c++中我們就可以在函數的參數給于初值,在我們調用函數的時候我們就可以不用給函數指派。也就是相當于我們生活中的備胎,如果沒有給于初值,就使用我們在函數定義的時候給于的初值,在我們給于了值後我們就使用我們調用函數給于的值

  • 全預設參數

    就是函數中所有的參數都給定了預設的值

  • 半預設參數

    在函數中隻有一部分的參數給定了預設的值

    注意點:

    半預設參數必須從右到左一次來給出,不能間隔

    預設參數不能在函數聲明和定義中同時出現

    預設值必須是常量或者全局變量

    c語言不支援

int add(int a,int b = 10);
           

在調用的時候我們就可以

cout << add(4) <<endl;
cout << add(4,20) <<endl;
           

輸出的結果就是14和24;

  1. 函數重載

    函數重載就是函數名相同,函數的參數的個數類型,順序必須不同就是函數的重載。

int add(int x,int y){
	return x+y;
}
double add(int x,int y){
	return x+y;
}
           

上面兩個函數就是重載的函數

那為什麼c++能夠去支援我們的函數重載呢?

重點一個c/c++程式要運作的話就需要盡力預處理、編譯、彙編、連結四個步驟。在我們的https://blog.csdn.net/boke_fengwei/article/details/88724548部落格中講解了我們的四個步驟的詳細過程。在c語言中名字修飾就在函數的名字前面加上下劃線,在c語言中如果有相同的函數名的時候就會連結錯誤,因為在底層有兩個相同的函數名字,但是在c++中我們是使用的函數名加上我們的參數類型來命名的。比如我們上面的兩個函數會命名成_addii和_adddd就形成了兩個不同的函數。c語言對于兩個函數都會形成_add。這就是為什麼我們的c++滿足函數重載,但是我們的c語言不支援函數重載。

挖根揭底就是我們的函數名的修飾規則導緻了我們的c++能夠支援函數重載。保證了我們的名字在底層的全局唯一性。

  1. 引用

    引用是我們c++中的一個新類型。它并不是定義了一個新的變量,而是給已存在的周遊取了一個别名而已,編譯器不會給引用變量開辟記憶體空間。

    使用方法:類型& 引用變量名 = 引用實體 (引用的類型必須和引用實體的類型相同)

void test{
	int a = 10;
	int& newa = a;
}
           

引用的特性:

  • 引用在定義的時候必須初始化。

    這個你可以了解在我們不初始化的時候我們定義的引用并不知道我們的引用指向的記憶體是哪裡,防止我們在未讓我們的引用指向一塊有效空間前使用它我們需要在定義的時候就初始化

  • 一個變量可以有多個引用

    就相當于我們每個人就有很多的稱謂一樣,但是實質上這個稱謂都是指向的是你。

  • 引用一旦引用一個實體,再不能引用其他實體

    這個其實跟我們的引用底層實作的本質有關。

引用的使用:

  • 常引用:就是引用我們的常量的時候我們不能按照正常的引用,需要加上關鍵字const來修飾
void test(){
	const int a = 10;
	//int &ra = a;此時會報錯
	const int &ra = a;
}
           
  • 做參數和傳回值

    做參數的時候就是傳遞的我們引用類型,就是相當于傳遞的一個值,他的位址指向我們函數調用的值。跟我們c語言中傳遞指針類似。在函數中對引用類型的修改,其實就是對我們的原資料進行修改。在c語言中我們傳遞我們的結構體的時候使用的是傳遞指針的方式,用于減少我們的拷貝的消耗,在c++中使用我們的引用同樣也可以達到效果,比我們直接傳值開銷更少。

//做參數
void Swap(int &a,int &b){
	int temp = a;
	a = b;
	b = temp;
}
           

做傳回值的時候就相當于傳回的實體對象

//做傳回值
int& add(int& a){
	a+=10;
	return a;
}
           

注意:如果函數傳回時,離開函數作用域後,其棧上空間已經返給系統,是以不能用棧上空間作為引用類型作為傳回值。如果要使用引用類型作為傳回值的話,傳回值的聲明周期必須不受函數的限制,也就是說要比函數的聲明周期長。

引用和指針的不同點:

  • 引用在定義時我們需要初始化,指針不需要
  • 引用在初始化一個實體之後我們就不能在指向其他實體,但是指針可以在任何時候指向任何一個實體
  • 沒有NULL引用,但是有NULL指針
  • 引用自加自減是實體加減1,指針自加自減向前/後偏移一個類型的大小
  • sizeof的含義不同。引用傳回的是一個實體的大小,但是指針傳回跟系統有關系
  • 傳回實體的方式不同,指針需要解引用,引用編譯器自己處理
  • 引用比指針使用起來更加安全

    引用的底層實作:

    引用在底層就是用常量指針來實作的。

  1. 内聯函數

    以inline修飾的函數叫做内聯函數,編譯時c++編譯器會在調用内聯函數的地方展開。沒有函數的壓棧,是以效率很高。

inline int add(int x,int y){
	return x+y;
}
int main(){
	int x =  10;
	int y = x+add(x,x);
}
           

此時會替換成

inline int add(int x,int y){
	return x+y;
}
int main(){
	int x =  10;
	int y = x+(x,x);
}
           

特性:

  • 以空間換時間的做法,省去了調用函數額外的開銷,
  • inline對于編譯器而言隻是一個建議,編譯器會自動優化,如果定義的inline函數體内有循環等等,編譯器優化時會忽略掉内聯
  • 不加我們的inline關鍵字的時候我們的函數也可以是内聯函數,這都是我們的編譯器作出的優化。

宏的優缺點?

優點:增強代碼的複用性,提高性能

缺點

  • 不友善調試
  • 導緻代碼可讀性差,可維護性差,容易誤用
  • 沒有類型安全檢查

    c++對于宏的替換

  • 常量第一換用const
  • 函數定義換用内聯函數。