目錄
一.引用
引用的特征:1.引用必須初始化
2.本質是別名
3.函數參數傳遞
4.常引用
5.函數返回值
6.權限 放大 縮小 平移
引用 vs 指針
二.內聯函數
關鍵點說明
三.宏函數
四.類
什么是類?
簡單的類
五.構造函數與析構函數
1. 構造函數(Constructor)
使用環境:
2. 析構函數(Destructor)
作用
示例
總結
六.this指針
1.?什么是?this?指針?
2. 為什么需要?this?指針?
3.?注意事項
七.拷貝構造函數
一、什么是拷貝構造函數?
二、淺拷貝(Shallow Copy)
什么是淺拷貝?
淺拷貝的問題
三、深拷貝(Deep Copy)
什么是深拷貝?
深拷貝解決方案
四、關鍵總結
一.引用
引用:引用不是新定義一個量而是給已存變量取一個別名,它和它引用的變量共用一塊空間
引用的特征:
1.引用必須初始化
引用必須在聲明時初始化,且不能重新綁定到其他對象。
int x = 10;
int &ref = x; // 正確:引用必須初始化
// int &ref2; // 錯誤:未初始化的引用
2.本質是別名
引用是變量的另一個名字,沒有獨立的內存地址,操作引用等價于操作原變量。
int x = 10;
int &ref = x; // 正確:引用必須初始化
// int &ref2; // 錯誤:未初始化的引用
3.函數參數傳遞
引用常用于函數參數,避免拷貝開銷且允許修改實參(替代指針的簡潔語法)。
void swap(int &x, int &y) {int temp = x;x = y;y = temp;
}int main() {int a = 1, b = 2;swap(a, b); // 直接傳遞變量,無需取地址cout << a << " " << b; // 輸出 2 1
}
4.常引用
常引用可以綁定到臨時對象或字面量,且不能通過引用修改原對象。
const int &r1 = 42; // 正確:常引用可綁定到字面量
int x = 10;
const int &r2 = x; // 正確:r2 是 x 的只讀別名
// r2 = 20; // 錯誤:不能通過常引用修改值
5.函數返回值
引用可以作為函數返回值,但需確保返回的對象生命周期有效(避免懸空引用)。
int global = 100;int& getGlobal() {return global; // 返回全局變量的引用(安全)
}int& dangerous() {int local = 50;return local; // 錯誤:返回局部變量的引用(懸空引用)
}
6.權限 放大 縮小 平移
int main()
{//權限不能放大//const int a = 0;//int& b = a;//可以只是一個拷貝const int c = 0;int d = c;//引用過程中權限可以平移或者縮小int x = 0;int& y = x;//權限的平移const int& z = x;//權限的縮小++x;//可以,因為上面是縮小了z的權限//不可以++z;double dd = 1.11;int ii = dd;// 不可以 int& rii = dd;const int& rii = dd;//臨時變量具有常性return 0;
}
引用 vs 指針
特性 | 引用 | 指針 |
---|---|---|
初始化 | 必須初始化 | 可以聲明后賦值 |
重新綁定 | 不能 | 可以 |
空值 | 不能為空 | 可以為?nullptr |
內存占用 | 無獨立內存地址 | 有自己的內存地址 |
語法簡潔性 | 直接操作對象(無需?* ?或?-> ) | 需要解引用操作符(* ?或?-> ) |
二.內聯函數
內聯函數建議編譯器將函數體直接插入調用位置(類似宏展開),以減少函數調用的開銷(壓棧、跳轉、返回等)。適用于短小且頻繁調用的函數。
#include <iostream>// 1. 使用 inline 關鍵字聲明內聯函數
inline int add(int a, int b) {return a + b;
}// 2. 類內定義的成員函數默認是內聯的
class Calculator {
public:int multiply(int a, int b) { // 隱式內聯return a * b;}inline int subtract(int a, int b) { // 顯式內聯return a - b;}
};int main() {int x = 5, y = 3;// 調用內聯函數 addstd::cout << "加法結果: " << add(x, y) << std::endl; // 編譯器可能直接替換為 x + yCalculator calc;// 調用類內聯函數std::cout << "乘法結果: " << calc.multiply(x, y) << std::endl;std::cout << "減法結果: " << calc.subtract(x, y) << std::endl;return 0;
}
關鍵點說明
-
inline
?關鍵字
用于建議編譯器將函數內聯,但最終是否內聯由編譯器決定(可通過編譯器優化選項控制,如?-O2
)。 -
類成員函數的內聯性
- 在類內部直接定義的成員函數(如?
multiply
)默認是內聯的。 - 也可以在類外定義成員函數時使用?
inline
?關鍵字(需在頭文件中實現)。
- 在類內部直接定義的成員函數(如?
-
適用場景
- 函數體短小(如 1-3 行代碼)。
- 頻繁調用且對性能敏感的場景(如循環中的操作)。
-
注意事項
- 避免內聯復雜函數(如遞歸函數或包含循環的函數)。
- 內聯函數定義必須對調用者可見,通常直接寫在頭文件中。
三.宏函數
?優點-- 不需要建立棧幀,提高調用效率
?缺點-- 復雜,容易出錯、可讀性差、不能調試
舉例三個問題的宏函數
以
Add(a | b, a & b); // (a | b + a & b)
為例:
以下三個有問題:
#define Add(int x, int y) return (x+y);
#define Add(x, y) x+y
#define Add(x, y) (x+y)
原因:(+ 與- 的優先級大于| 與&)
成功示范:
?
#define Add(x, y) ((x)+(y))
四.類
什么是類?
- 類是對象的“藍圖”或“模板”,用于定義對象的屬性(成員變量)和行為(成員函數)。
- 通過類可以創建具體的對象(實例),每個對象擁有獨立的屬性值。
- 類的核心思想是封裝:將數據和對數據的操作綁定在一起,并控制外部對數據的訪問權限。
簡單的類
#include <iostream>
using namespace std;// 定義一個 Person 類
class Person {
public: // 公有成員,外部可以直接訪問char name; // 成員變量:姓名int age; // 成員變量:年齡// 成員函數:顯示信息void display() {cout << "姓名: " << name << ", 年齡: " << age << endl;}
};int main() {// 創建 Person 類的對象Person person1;// 設置對象的屬性person1.name = "張三";person1.age = 25;// 調用對象的方法person1.display(); // 輸出:姓名: 張三, 年齡: 25return 0;
}
封裝:通過?private
?隱藏內部細節,通過?public
?提供安全接口
五.構造函數與析構函數
1. 構造函數(Constructor)
作用
- 在對象創建時自動調用,用于初始化對象的成員變量。
- 可以重載(定義多個不同參數的構造函數)。
- 沒有返回類型,且名稱與類名相同。
默認構造函數:無參構造函數,全缺省構造函數,編譯器默認生成的構造函數
示例
構造函數:
class Person {
public:char name;int age;// 默認構造函數(無參數)Person() {name = "Unknown";age = 0;cout << "默認構造函數被調用" << endl;}// 帶參數的構造函數Person(string n, int a) {name = n;age = a;cout << "帶參數的構造函數被調用" << endl;}
};
使用環境:
int main() {Person p1; // 調用默認構造函數Person p2("Alice", 25); // 調用帶參數的構造函數return 0;
}
2. 析構函數(Destructor)
作用
- 在對象銷毀時自動調用,用于釋放對象占用的資源(如內存、文件句柄)。
- 名稱是類名前加?
~
,沒有參數和返回類型。 - 不能重載(每個類只有一個析構函數)。
示例
析構函數:
class FileHandler {
private:FILE* file;
public:// 構造函數:打開文件FileHandler(const char* filename) {file = fopen(filename, "r");cout << "文件已打開" << endl;}// 析構函數:關閉文件~FileHandler() {if (file) {fclose(file);cout << "文件已關閉" << endl;}}
};
使用場景:
?
int main() {Person p1; // 調用默認構造函數Person p2("Alice", 25); // 調用帶參數的構造函數return 0;
}
總結
特性 | 構造函數 | 析構函數 |
---|---|---|
調用時機 | 對象創建時 | 對象銷毀時 |
主要用途 | 初始化成員變量 | 釋放資源(如內存、文件) |
重載 | 支持重載(多個構造函數) | 不支持重載(唯一析構函數) |
默認生成 | 未定義時編譯器生成默認構造函數 | 未定義時編譯器生成默認析構函數 |
通過合理使用構造函數和析構函數,可以確保對象在生命周期內正確初始化和清理資源,避免內存泄漏和邏輯錯誤。
六.this指針
1.?什么是?this
?指針?
在 C++ 中,this
?是一個指向當前對象的指針。
- 每個類的非靜態成員函數(包括構造函數和析構函數)內部都可以訪問?
this
。 this
?指針是隱式存在的,不需要手動定義。- 它的類型是?
ClassName*
(例如,Person*
、Car*
)。
class Person {
public:string name;void printName() {// 實際上等價于:cout << this->name << endl;cout << name << endl;}
};
2. 為什么需要?this
?指針?
當你在類的成員函數中訪問成員變量或調用成員函數時,編譯器實際上是通過?this
?指針來找到當前對象的成員。
例如:
class Person {
public:string name;void printName() {// 實際上等價于:cout << this->name << endl;cout << name << endl;}
};
3.?注意事項
this
?是一個指針靜態函數屬于類,而不是對象,因此不能使用?this
。this指針是形參所以是存在棧中的
class MyClass {
public:static void staticFunc() {// this->xxx; // 錯誤!靜態函數沒有 this}
};
七.拷貝構造函數
一、什么是拷貝構造函數?
拷貝構造函數是一個特殊的構造函數,用于通過已存在的對象創建一個新對象。當發生以下情況時會自動調用:
- 用已有對象初始化新對象
- 對象作為函數參數傳遞(值傳遞)
- 對象作為函數返回值(值返回)
基本語法:
ClassName(const ClassName& other);
二、淺拷貝(Shallow Copy)
什么是淺拷貝?
- 默認的拷貝構造函數是淺拷貝
- 直接復制成員變量的值(包括指針地址)
- 如果類中有指針成員,會導致多個對象指向同一塊內存
淺拷貝的問題
class ShallowCopy {
public:int* data;//構造函數ShallowCopy(int val) {data = new int(val); // 動態分配內存}// 默認拷貝構造函數是淺拷貝:ShallowCopy(const ShallowCopy& other) = default;//析構函數~ShallowCopy() {delete data; // 釋放內存}
};int main() {ShallowCopy obj1(10);ShallowCopy obj2 = obj1; // 淺拷貝// 問題:obj1和obj2的data指向同一塊內存// 當main結束時,obj2先調用析構函數釋放內存// 然后obj1的析構函數會嘗試釋放已釋放的內存 → 程序崩潰!
}
三、深拷貝(Deep Copy)
什么是深拷貝?
- 需要手動實現拷貝構造函數
- 為指針成員分配新的內存
- 復制指針指向的內容,而不是復制指針地址
深拷貝解決方案
class DeepCopy {
public:int* data;DeepCopy(int val) {data = new int(val);}// 手動實現深拷貝構造函數DeepCopy(const DeepCopy& other) {data = new int(*other.data); // 分配新內存并復制值}// 注意:還需要重載賦值運算符(規則同理)DeepCopy& operator=(const DeepCopy& other) {if (this != &other) {delete data; // 釋放原有內存data = new int(*other.data); // 深拷貝}return *this;}~DeepCopy() {delete data;}
};int main() {DeepCopy obj1(20);DeepCopy obj2 = obj1; // 深拷貝// obj1.data 和 obj2.data 指向不同內存// 析構時不會出現重復釋放問題
}
四、關鍵總結
淺拷貝 | 深拷貝 | |
---|---|---|
復制內容 | 復制指針地址 | 復制指針指向的內容 |
內存安全性 | 多個對象共享同一內存,易導致崩潰 | 每個對象擁有獨立內存,安全可靠 |
實現方式 | 默認拷貝構造函數 | 需要手動實現拷貝構造函數 |
適用場景 | 無動態內存分配的簡單類 | 有指針成員或動態分配資源的類 |