-
bool類型
取值:true,false。
大小:VC占1個位元組。
-
const限定符
常量(常變量)聲明形式:
const 資料類型 常量名=常量值; 資料類型 const 常量名=常量值;
注:上面兩者等價。
例子說明:
#include <iostream> using namespace std; int main(void) { //const int a; Error,常量必須初始化 const int a = 100; //a = 200; Error,常量不能重新被指派 int b = 22; const int * p; //const在*左邊,表示*p為常量,經由*p不能更改指針所指向的内容 p = &b; //*p = 200; Error,常量不能重新被指派 //int * const p2; Error,p2為常量,常量必須初始化 int * const p2 = &b; //const在*右邊,表示p2為常量 //int c =100; //p2 = &c; Error,常量不能重新被指派 *p2 = 200; cout<<b<<endl; return 0; }
-
const與#define
const定義的常量與#define定義的符号常量的差別:
前者有類型,要進行類型檢查,後者隻是單純的替換;
前者在編譯期配置設定記憶體,後者在預處理期替換,不配置設定記憶體;
作用域不同,前者的作用域與一般的變量的作用域相同,後者為定義處到程式結束,可以使用#undef取消。
#define容易産生副作用
#define中#,##的使用//Effective C++ 3rd的一個例子。 #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被累加一次 // 在這裡,調用f之前,a的遞增次數竟然取決于“它被拿來和誰比較”
#include <iostream> using namespace std; //#define STR(a) a // 不使用#,使用STR(a),a未聲明,會報錯。 #define STR(a) #a // 字元串化,當這裡使用#,你使用STR(a),a未聲明,會被轉化成字元串"a"。 #define CAT(a, b) a##b // 連接配接作用 int main() { int ab = 100; const char *str = STR(a); cout <<str << endl; //"a" cout << CAT(a, b) << endl; // 100 return 0; }
-
結構體對齊
什麼是結構體對齊?
編譯器為每個“資料單元”按排在某個合适的位置上。 C、C++語言非常靈活,它允許你幹涉“記憶體對齊”。
為什麼要對齊?
性能原因:在對齊的位址上通路資料快。
對齊方法
1.第一個變量與結構體變量的偏移量為0;
2.計算每個變量的對齊數(編譯器設定的對齊數與該成員大小的較小值);
3.每個成員變量 的位址為:對齊數的整數倍;對其到對齊數整數倍的位址;
4.結構體總大小為最大對齊數的整數倍。
對齊案例
// vc++預設對其整數為8,g++預設為4 // 在屬性->C/C++->代碼生成可以修改 // 或者 #pragma pack(8)修改 // #pragma pack()取消修改 /* struct MyStruct { char ch; // 0 double db; // 8 int it; // 16-23 }; // 24*/ /* struct MyStruct { char ch; // 0 int it; // 4 double db; // 8-15 }; // 16*/ /* struct MyStruct { char ch1; // 0 int it; // 4 char ch2; // 8 double db; // 16-23 }; // 24*/ struct MyStruct { double db1; //0 char ch1; //8 float ft; //12 int it; // 16 char ch2; // 20 double db2; // 24-31 }; // 32
- 域運算符 作用: 用于對與局部變量同名的全局變量進行通路; 用于表示類的成員。
-
new、delete運算符
new文法:
指針變量=new 資料類型(初始化參數-可選);
指針變量=new 資料類型[長度n];
delete文法:
delete 指針變量;
delete [] 指針變量;
new一個新對象過程:
記憶體配置設定(operator new)
調用構造函數
delete一個對象過程:
調用析構函數
釋放記憶體(operator delete)
operator new/new operator/placement new:
operator new:隻配置設定記憶體
new operator:調用構造函數 + 配置設定記憶體
placement new:不配置設定記憶體,調用拷貝構造函數
-
重載
函數重載:又稱為函數的多态(靜态多态),編譯時期指定函數入口位址,靜态聯編。
成立條件:
形參數量不同; 形參類型不同; 形參的順序不同; 形參數量和形參類型都不同。
注:函數重載跟函數的傳回值無關。 派生類與基類通過虛函數實作的多态(動态多态),運作時期指定函數入口位址,動态聯編。
-
name managling與extern “C”
name managling:就是将函數的名字修改,實作函數重載。
extern "C"使用:
#ifdef __cpluscplus extern “C” { #endif ... #ifdef __cpluscplus } #endif
-
帶預設參數的函數
幾點說明:
1.函數既有定義又有聲明時,聲明時指定後,定義後就不能再指定預設值;
2.預設值的定義必須遵守從右到左的順序,如果某個形參沒有預設值,則它左邊的參數就不能有預設值;
3.函數調用時,實參與形參按從左到右的順序進行比對
-
引用
幾點說明:
1.引用在定義的時候要進行初始化;
2.引用一經初始化,不能重新引用其他變量;
3.非const引用不能引用const常量;
4.double val3 = 3.14;const int& ref4 = val3;隻是報警告,等價于定義一個臨時變量int tmp = 3,然後讓ref4去引用tmp,當ref4不是常引用的時候,編譯器直接報類型轉換錯誤(強類型)。
5.同理4,const int &ref = 10;常引用使用字面量初始化自然就是有效的。
6.不能傳回對局部變量的引用,通過傳回引用,可以讓函數調用作為左值,改變全局或者靜态變量的值(通常在函數中傳回靜态或者全局變量的引用)。
7.教課書上說的是引用不配置設定記憶體空間,但是不是與引用是使用指針實作的沖突麼?
-
内聯函數
幾點說明:
1.不能有遞歸
2.不能包含靜态資料
3.不能包含循環
4.不能包含switch和goto語句
5.不能包含數組
注:若一個内聯函數定義不滿足以上限制,則編譯系統把它當作普通函數對待。
内聯函數與帶參數宏差別
一樣是内聯函數要進行類型檢查,宏隻是簡單的替換。
-
類型轉換
舊式轉換
(T)expr T(expr) 新式轉換
const_cast<T>(expr)
void change(const int &r) { int &rr = const_cast<int &>(r); rr = 200; } void test(int &r) { r = 100; } int main(void) { int n = 100; const int *pn = &n; const int &rn = n; //const_cast一般用于指針或者引用 // 個人覺得const_cast應該應用到該場景 // 即變量本身是變量,但是被常量指針或者常引用引用了 // 希望通過指針,或者引用去修改最初變量的值 int *p = const_cast<int *>(pn); *p = 200; cout << n << endl; // 200 int &r = const_cast<int &>(rn); r = 300; cout << r << endl; const int val = 100; // 常量本身是不能更改的,最多你能更改它在記憶體中的值,當使用該常量時,它去常量表直接取值 // int varl = const_cast<int>(val); //Error, 無法從“const int”轉換為“int” int m = 10; change(m); cout << m << endl; // 200 //使用const_cast去除const限定的目的不是為了修改它的内容 //使用const_cast去除const限定,通常是為了函數能夠接受這個實際參數 const int a = 10; //test(a); // Error, 從“const int”轉換為“int &” test(const_cast<int&>(a)); // 隻是修改了a在記憶體中的值,a本身的值不會修改,在常量表中 return 0; }
static_cast<T>(expr)
了解成一般的強制轉換即可。
reinterpret_cast<T>(expr)
“通常為操作數的位模式提供較低層的重新解釋”也就是說将資料以二進制存在形式的重新解釋。
int main(void) { int i; char *p = "This is a example."; i = reinterpret_cast<int>(p); //此時結果,i與p的值是完全相同的。 //cout << p << endl; // This is a example. cout << i << endl; // 13032560,cout 見int型,那麼直接相當于printf的%d輸出了他的位址 printf("%s\n", i); // This is a example. printf("%d\n", i); // 13032560 printf("%s\n", p); // This is a example. printf("%d\n", p); // 13032560 int m = 10; int *ip = &m; char *pc = reinterpret_cast<char*>(ip); // 程式員需要記得pc所指向的真實對象是int型,并非字元串。 // 如果将pc當作字元指針進行操作,可能會造成運作時錯誤 // 如int len = strlen(pc); printf("%d\n", *pc); // 10 return 0; }
dynamic_cast<T>(expr)
執行“安全向下”轉型操作,也就是說支援運作時識别指針或所指向的對象,這是唯一個無法用舊式語來進行的轉型操作。
轉載于:https://www.cnblogs.com/ifpelset/articles/4505648.html