【01】C到C++(基礎)

zhuhurry發表於2018-07-15
版權宣告:zhuhurry 未經博主允許不得轉載    https://blog.csdn.net/zhuhurry


為什麼要學C++:

C++是更高階的C語言,在保證C語言執行效率的同時具有現在語言的特性、在工業等效能要求較高的領域運用廣泛
C與C++的區別簡介
C語言是一個結構化語言,重在演算法和資料結構,它是程式導向的程式設計思想
C++全面相容C,支援C風格、基於物件、物件導向、泛型、函式式5種程式設計方式

一、bool 布林型
其值為true(邏輯真)和false(邏輯假),儲存的位元組在不同的編譯系統中不同,vc++中為1個位元組。可以當作整數用(true一般為1,false為0)
宣告方式:bool result
把其它型別的值轉換為布林值時,非零值轉換為true,零值轉換為false

二、const 限定符
C++ const 允許指定一個語義約束,編譯器會強制實施這個約束,允許程式設計師告訴編譯器某值是保持不變的。如果在程式設計中確實有某個值保持不變,就應該明確使用const,這樣可以獲得編譯器的幫助。
提高程式的效率:編譯器通常不為普通const常量分配儲存空間,而是將它們儲存在符號表中,這使得它成為一個編譯期間的常量,沒有了儲存與讀記憶體的操作,使得它的效率也很高。

1.修飾變數
int const a= 100;//兩種修飾方法效果一致,變數a的值不可變,必須要初始化
const int a= 100;
2.修飾指標
const int * p; //const在*左邊,表示*p為常量,即p指向的內容不可變
int* const p; //const在*右邊,表示p為常量,指標本身是常量不可變
const int* const p; //兩者都不可變
3.const修飾引數和返回值
(1)const修飾函式引數
void function(const int Var); //傳遞過來的引數在函式內不可以改變(無意義,因為Var本身就是形參,不會改變實參)
void function(const char* Var); //引數指標所指內容為常量不可變
void function(char* const Var); //引數指標本身為常量不可變(也無意義,因為char* Var也是形參)
void function(const int& Var); //引用引數在函式內為常量不可變,引數為引用,為了增加效率同時防止修改,C++中比較常見
(2)const 修飾函式返回值
const修飾函式返回值其實用的並不是很多,它的含義和const修飾普通變數以及指標的含義基本相同。
4.const修飾類的成員函式
const修飾的成員函式不能修改任何的成員變數
const成員函式不能呼叫非onst成員函式,因為非const成員函式可以會修改成員變數

三、#define使用及在定義常量時和const的區別
1.const定義的常量有型別,而#define定義的沒有型別,編譯可以對前者進行型別安全檢查,而後者僅僅只是做簡單替換
2.const定義的常量有型別,而#define定義的沒有型別,編譯可以對前者進行型別安全檢查,而後者僅僅只是做簡單替換
3.作用域不同,const定義的常變數的作用域為該變數的作用域範圍。而#define定義的常量作用域為它的定義點到程式結束,當然也可以在某個地方用#undef取消

#define 替換 在底層實現的時候應用廣泛
#define注意出錯的地方:
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
int a = 5;
int b = 0;
CALL_WITH_MAX(++a, b); //a被累加二次
CALL_WITH_MAX(++a, b+10); //a被累加一次

四、結構體記憶體對齊
記憶體對齊:編譯器為每個“資料單元”按排在某個合適的位置上,C、C++語言非常靈活,它允許你干涉“記憶體對齊”。
為什麼要對齊
效能原因:在對齊的地址上訪問資料快。
如何對齊
(1)第一個成員與結構體變數的偏移量為0
(2)其它成員要對齊到對齊數的整倍數的地址,(注意是地址
(3)對齊數取編譯器預設的一個對齊整數與該成員大小的較小值
(4)結構體總大小為最大對齊數的整數倍
如何幹涉“記憶體對齊”
#pragma pack(1) //指定編譯器的對齊整數
struct test{}; //需要對齊的結構體
#pragma pack() //取消設定的對齊整數

五、域運算子(C++新增)::
用於對與區域性變數同名的全域性變數進行訪問
用於表示類的成員,這將在關於類的一節中詳細說明



六、new、delete運算子
new運算子可以用於建立堆空間,成功返回首地址
指標變數=new 資料型別 int *p; p=new int;
指標變數=new 資料型別[長度n]; char *pStr=new char[50];
delete運算子 可以用於釋放堆空間
delete 指標變數; delete p;
delete [] 指標變數; delete [] pStr;
new一個新物件
記憶體分配(operator new)
呼叫建構函式
delete釋放一個物件
呼叫解構函式
釋放記憶體(operator delete)

七、過載
相同的作用域,如果兩個函式名稱相同,而引數不同,我們把它們稱為過載overload,函式過載又稱為函式的多型性,呼叫過載函式時,編譯器通過檢查實際引數的個數、型別和順序來確定相應的被呼叫函式。
函式過載不同形式:
形引數量不同 形參型別不同
形參的順序不同 形引數量和形參型別都不同
注意,如果函式的返回型別不同,但函式名、引數相同,則不是過載,編譯器報錯

八、name managling與extern “C”
name managling這裡把它翻譯為名字改編C++為了支援過載,需要進行name managling
extern “C”實現C與C++混合程式設計, 即對C語言寫的函式不進行改名。如果我們在c++編譯環境中沒有使用extern “C”來引用C的函式,則C++編譯器會對其函式名進行改編,則找不到對應的函式實現。
我們一般書寫格式如下:
#ifdef __cpluscplus //如果是C++編譯器,則引用extern “C”
extern “C”
{
#endif
...
#ifdef __cpluscplus
}
#endif
這樣書寫的方便之處是當書寫的程式碼可用於C和C++語言,不需要做修改。

九、帶預設形參值的函式
函式宣告或者定義的時候,可以給形參賦一些預設值、呼叫函式時,若沒有給出實參,則按指定的預設值進行工作。

需要注意的地方:
1.若函式具有多個形參,則預設形參值必須自右向左連續地定義,並且在一個預設形參值的右邊不能有未指定預設值的引數。
void func1(int a, double b=4.5, int c=3); //合法的
void func1(int a=1, double b, int c=3); //不合法的
在呼叫一個函式時,如果省去了某個實參,則直到最右端的所有實參都省去
int f(int a, float b=5.0, char c='c', int d=10);
f(9,4.5) == f(9,4.5,'c') == f(9,4.5,'c',10)
2.預設形參值的說明必須出現在函式呼叫之前,如果存在函式的宣告則在函式的宣告中給預設值,一般不再函式定義中給預設值。如果不存在很熟宣告則在函式定義中給預設值。若函式原型中已給出了形參的預設值,則在函式定義中不得重複指定,即使所指定的預設值完全相同也不行。
int sub(int x=8,int y=3);
int sub(int x=8,int y=3){ //不合法、重複指定
return x+y;
}
需要注意的錯誤:

sum=add(10,20)語句產生二義性性,可以認為該語句是呼叫第一個函式,也可以是第二個,因此編譯器不能確定呼叫的是哪一個函式。

十、namespace名稱空間
所謂namespace,是指識別符號的各種可見範圍。C++標準程式庫中的所有識別符號都被定義於一個名為std的namespace中。
為了避免在大規模程式的設計中識別符號名稱發生衝突,標準C++引入了namespace,可更好的控制識別符號的作用域。c++標準為了和C區別開,也為了正確使用名稱空間,規定標頭檔案不使用字尾.h。
C語言中只有一個全域性作用域,所有的識別符號共享一個作用域,識別符號之間可發生衝突,而在C++中,名稱空間將全域性作用域分成不同的部分,不同名稱空間中的識別符號可以同名而不會發生衝突命令空間可以相互巢狀,全域性作用域也叫預設名稱空間
名稱空間的定義:
namespace name {...}
名稱空間的使用:
使用整個名稱空間:using namespace name
使用名稱空間中的變數:using name::variable
使用預設名稱空間中的變數: ::variable
預設情況下可以直接使用預設名稱空間中的所有識別符號

十一、“實用性”增加
C語言中的變數都必須在作用域開始的位置定義
C++中更強調語言的“實用性”,所有的變數都可以在需要使用時再定義

十二、register關鍵字增強
在C和C++中,這個關鍵字請求編譯器儘可能的將變數存在CPU內部暫存器中,而不是通過記憶體定址訪問,以提高效率。注意是儘可能,不是絕對。假如,CPU內部暫存器不夠時,該變數就是一個普通的變數。
在C中:
register可以在全域性中定義變數,當對其使用&時,只是警告“有壞的儲存類”
register可以在區域性作用域中宣告,但這樣就無法對其使用&。否則編譯不通過
在C++中:
register無法在全域性中定義變數,否則會被提示為不正確的儲存類
register在區域性作用域中宣告時,可以用&操作符取地址,一旦使用了取地址操作符,被定義的變數會強制存放在記憶體中
總之:
建議不要用register定義全域性變數,因為全域性變數的生命週期是從執行程式開始,一直到程式結束才會終止,而register變數可能會存放在cpu的暫存器中,如果在程式的整個生命週期內都佔用著暫存器的話,這是個相當不好的舉措。

十三、struct型別加強
C語言的struct定義了一組變數的集合,C編譯器並不認為這是一種新的型別
C++中的struct是一個新型別的定義宣告,與類功能相同



















相關文章