網(wǎng)站數(shù)字證書怎么做百度快照推廣效果怎樣
C/C++復習 day1
文章目錄
- C/C++復習 day1
- 前言
- 一、C語言
- 1.memcpy函數(shù)
- 2.memmove函數(shù)
- 3.strstr函數(shù)
- 4.宏定義的函數(shù)
- 5.大小端的介紹以及判斷
- 二、C++入門基礎
- 1.C++是如何支持函數(shù)重載的?
- 2.建議用const enum inline去替代宏
- 三、C++類和對象
- 1.類大小的計算
- 2.移動構造和移動賦值
- 1.右值引用
- 2.move關鍵字
- 3.模板右引用
- 4.完美轉(zhuǎn)發(fā)
- 5.移動構造和移動賦值
- 3.初始化列表
- 1.初始化列表的特性
- 2.哪些類型必須在初始化列表中初始化?
- 4.運算符重載
- 1. 不支持重載的運算符
- 2.自定義類型轉(zhuǎn)化內(nèi)置類型
- 3. 內(nèi)存管理
- 1.new delete 和 malloc free的區(qū)別
- 2.new 和 new[]底層實現(xiàn)原理
- 3.內(nèi)存泄露問題
- 1.什么是內(nèi)存泄漏?
- 2.內(nèi)存泄漏的危害
- 3.如何解決內(nèi)存泄漏
- 1.RAII 智能指針
- 2.使用內(nèi)存泄漏檢查工具
- 總結
前言
隨著C++課程的學習結束,接下來回顧一下C和C++中的難點,看看有什么是遺漏的。
一、C語言
1.memcpy函數(shù)
void* my_memcpy(void* des, const void* src, size_t num)
{assert(des != NULL && src != NULL);void* begin = des;for (size_t i = 0; i < num; i++){*(char*)des = *(char*)src;des = (char*)des + 1;src = (char*)src + 1;}return begin;
}
按照字節(jié)數(shù)去拷貝賦值
2.memmove函數(shù)
// 從右往左移動則小到大賦值 從左往右復制,則從大到小賦值
void* my_memmove(void* des,const void* src,size_t num)
{assert(des!=NULL && src!=NULL);void* begin = des;if (des < src){for (size_t i = 0; i < num; i++){*(char*)des = *(char*)src;des = (char*)des + 1;src = (char*)src + 1;}}else{for (size_t i = num-1; i!=-1; i--){*((char*)des + i) = *((char*)src + i);}}return begin;
}
注意賦值順序
3.strstr函數(shù)
char* my_strstr(char* str1,const char* str2)
{int i = 0, j = 0;int flag = 0;char* begin = NULL;char* p1 = str1, *p2 = str2;while (p1[i] != '\0' && p2[j] != '\0'){if (p1[i] == p2[j]){if (flag == 0){begin = p1+i;flag = 1;}i++;j++;}else{i = i - j + 1;j = 0;flag = 0;}}if (p2[j] == '\0'){return begin;}else{return NULL;}
}
4.宏定義的函數(shù)
#define ADD(x,y) ((x)+(y))
5.大小端的介紹以及判斷
大小端
int main()
{// 判斷大小端 01 00 00 00 01// 大端 01 02 03 04// 00 00 00 01// 小端 01 02 03 04// 01 00 00 00int i = 1;if (*(char*)&i == 1){printf("小端\n");}else if (*(char*)(&i) == 0){printf("大端\n");}
}
二、C++入門基礎
1.C++是如何支持函數(shù)重載的?
函數(shù)重載
C++支持函數(shù)重載而C語言不支持是因為函數(shù)在內(nèi)存中的存儲方式不相同,C語言是直接以函數(shù)名修飾,而C++是_Z 函數(shù)名長度 函數(shù)名 類型首字母,導致C++支持重載,而C語言不支持重載。
2.建議用const enum inline去替代宏
三、C++類和對象
1.類大小的計算
類大小的計算
總結:1.類大小的計算不包括static修飾的靜態(tài)的一系列東西,函數(shù)也不算在內(nèi)。
2. 類大小的計算要符合結構體的對齊規(guī)則。
3. 空類的大小為1。
4. 虛函數(shù)(多態(tài),重寫):要存放一個虛函數(shù)表,先存該父類的虛函數(shù)表,再存父類中的成員變量。
5. 虛繼承,父類中要多存放一個偏移量。
2.移動構造和移動賦值
說起這兩個,就必須先提起C++11引入的右值引用和幾個關鍵字。
1.右值引用
int&& rr1=10;
double&& rr2 = x+y;
之前的一個&表示對變量的引用,現(xiàn)在兩個&&表示對右值的引用。
2.move關鍵字
比如我們正常這樣寫,編譯器會報錯不支持。
無法將左值綁定到右值引用。
int x=10;
int&& rr1 = x;
但是我們通過move關鍵字即可完成。
move僅僅是將變量的右值取出。
int x=10;
int&& rr1 = std::move(x);
3.模板右引用
對于模板來說,對于它&&,此時則既可以接受左值傳參,也可以接受右值傳參。也就是萬能引用。
void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }
template<class T>
void func(T&& value)
{fun(value);
}
如果我們執(zhí)行程序可以發(fā)現(xiàn),我們的輸出全是左值引用,這是為什么呢?
模板的萬能引用只是提供了能夠接收同時接收左值引用和右值引用的能力, 但是引用類型的唯一作用就是限制了接收的類型,后續(xù)使用中都退化成了左值。
因此,需要我們的完美轉(zhuǎn)發(fā)。
4.完美轉(zhuǎn)發(fā)
void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }
// std::forward<T>(t)在傳參的過程中保持了t的原生類型屬性。
template<typename T>
void PerfectForward(T&& t)
{Fun(std::forward<T>(t));
}
通過forward<模板>(參數(shù))即可實現(xiàn)完美轉(zhuǎn)發(fā),使左值按左值傳參,右值按右值傳參。
5.移動構造和移動賦值
移動構造和移動賦值
這樣寫避免了某些不必要的深拷貝。
noexcept關鍵字,表示該函數(shù)不會拋出異常。
注意賦值完,要對原對象進行處理,這里指針將其變?yōu)閚ullptr
3.初始化列表
1.初始化列表的特性
- 效率優(yōu)勢
初始化列表在對象成員的初始化過程中效率更高。對于一些內(nèi)置類型和沒有默認構造函數(shù)的類類型成員,如果在初始化列表中進行初始化,能避免額外的默認初始化和賦值操作。 - 初始化順序
成員變量的初始化順序是按照它們在類中的聲明順序,而不是在初始化列表中的順序。 - 成員對象初始化
對于類中的成員對象,使用初始化列表可以正確地調(diào)用其對應的構造函數(shù)進行初始化。 - 避免未定義行為
如果不使用初始化列表對某些成員進行初始化,可能導致未定義的行為,尤其是對于具有復雜依賴關系的成員。
2.哪些類型必須在初始化列表中初始化?
- const成員變量
class MyClass {const int myConstVar;
public:MyClass(int val) : myConstVar(val) {} // 必須在初始化列表中初始化
};
- 引用成員變量
class YourClass {int& myRefVar;
public:YourClass(int& var) : myRefVar(var) {} // 引用必須在初始化列表中初始化
};
- 沒有默認構造函數(shù)的類成員
class OtherClass {OtherClass(int x) {} // 自定義構造函數(shù),無默認構造函數(shù)
};class MainClass {OtherClass myOther;
public:MainClass(int val) : myOther(val) {} // 需在初始化列表中初始化
};
- 基類
當從基類派生出一個類,并且基類沒有默認構造函數(shù)時,則必須在初始化列表中進行初始化。
class Base {Base(int num) {}
};class Derived : public Base {
public:Derived(int num) : Base(num) {} // 初始化基類
};
4.運算符重載
1. 不支持重載的運算符
- 作用域操作符 ::
- 條件操作符 ?:
- 點操作符 .
- 預處理操作符 #
2.自定義類型轉(zhuǎn)化內(nèi)置類型
可以通過重載內(nèi)置類型來完成
例如,以下代碼將MyClass類轉(zhuǎn)化為int類型,此時重載函數(shù)不需要寫返回值。
class MyClass {
private:int value;public:MyClass(int val) : value(val) {}operator int() {return value;}
};int main() {MyClass obj(42);int num = obj; // 調(diào)用重載的 operator int 進行類型轉(zhuǎn)換std::cout << "Converted value: " << num << std::endl;return 0;
}
3. 內(nèi)存管理
1.new delete 和 malloc free的區(qū)別
區(qū)別
2.new 和 new[]底層實現(xiàn)原理
- new 會調(diào)用operator new 先去開辟空間,開辟完后再調(diào)用對應的構造函數(shù)進行初始化。
- new [] 會調(diào)用n次operator new去開辟空間,然后再去調(diào)用n次構造函數(shù)進行初始化。
3.內(nèi)存泄露問題
1.什么是內(nèi)存泄漏?
內(nèi)存泄漏指因為疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應用程序分配某段內(nèi)存后,因為設計錯誤,失去了對該段內(nèi)存的控制,因而造成了內(nèi)存的浪費。
由于引入了異常問題,在拋出異常后對應的內(nèi)存可能沒有進行釋放,久而久之就可能導致內(nèi)存泄漏。
2.內(nèi)存泄漏的危害
長期運行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺服務等等,出現(xiàn)
內(nèi)存泄漏會導致響應越來越慢,最終卡死。
3.如何解決內(nèi)存泄漏
1.RAII 智能指針
- auto_ptr
最早引入的智能指針,但不支持賦值 - smart_ptr
支持賦值,但是雙鏈表的循環(huán)會出現(xiàn)問題。 - weak_ptr
不增加計數(shù),用來解決循環(huán)問題。
2.使用內(nèi)存泄漏檢查工具
總結
以上就是C/C++的總結一,接下來應該還有需要補充修改的內(nèi)容。
本人小白一枚,有問題還望各位大佬指正。