
- C++ 基礎
- C++ 首頁
- C++ 概述
- C++ 環境設定
- C++ 基本語法
- C++ 註釋
- C++ Hello World
- C++ 省略名稱空間
- C++ 常量/字面量
- C++ 關鍵字
- C++ 識別符號
- C++ 資料型別
- C++ 數值資料型別
- C++ 字元資料型別
- C++ 布林資料型別
- C++ 變數型別
- C++ 變數作用域
- C++ 多個變數
- C++ 基本輸入/輸出
- C++ 修飾符型別
- C++ 儲存類
- C++ 運算子
- C++ 數字
- C++ 列舉
- C++ 引用
- C++ 日期和時間
- C++ 控制語句
- C++ 決策
- C++ if 語句
- C++ if else 語句
- C++ 巢狀 if 語句
- C++ switch 語句
- C++ 巢狀 switch 語句
- C++ 迴圈型別
- C++ while 迴圈
- C++ for 迴圈
- C++ do while 迴圈
- C++ foreach 迴圈
- C++ 巢狀迴圈
- C++ break 語句
- C++ continue 語句
- C++ goto 語句
- C++ 建構函式
- C++ 建構函式和解構函式
- C++ 複製建構函式
高階 C++ 概念
C++ 是現代程式設計的基礎語言之一。它從基本的 C 語言演變而來,成為現代程式設計中非常強大的工具。C++ 的版本從 C++ 98 開始,現在已經發展到 C++ 20。在 C++ 11 更新之後,所有現代更新都被統稱為現代 C++。這些新模型具有廣泛的新功能,使該語言更易於使用者使用,並具有更好的功能。其中一些新概念已經是其他新語言的一部分,例如 以太坊、Ruby、Python 和 Javascript,隨著這些概念在 C++ 中的引入,如今的程式設計效率更高。
以下是我們將詳細瞭解的不同高階 C++ 主題的列表:
隨著C++ 20版本的釋出,還提供了其他功能,這些功能稍微高階一些,將在本文的後面部分介紹。上面提到的功能也是非常高階的概念,但是本文提供的解釋足以讓讀者深入研究現代 C++ 語言。
RAII(資源獲取即初始化)

資源獲取即初始化,通常用其縮寫 RAII 指代,是一種用於記憶體管理的 C++ 技術。雖然它通常與 C++ 相關聯,這就是為什麼它被研究的原因,但 RAII 的範圍超出了語言限制的障礙。
簡單地說,RAII 意味著以建構函式的形式將記憶體分配給物件,然後使用解構函式釋放分配的記憶體。因此,它構成了OOP 概念的一部分,這在之前的主題中已經介紹過。
現在,您一定很好奇 RAII 到底解決了哪些問題?RAII 以多種方式工作,其中一些是:
這些主題中的一些已經在本文的前面部分討論過,一些新概念將在本文的後面部分討論。
現在,在程式設計中,尤其是在面向物件程式設計方面,資源究竟是什麼?
資源是在編譯或執行程式或一系列程式期間可能需要的實體。資源的示例包括棧、堆、記憶體、檔案、套接字(在套接字程式設計中)、鎖和訊號量等。這些資源對於程式的順利執行至關重要。程式透過請求獲取這些資源,例如,對於互斥鎖,使用 mutex() 方法呼叫來獲取。
在使用 C 的經典程式設計中,我們使用 new() 和 delete() 的概念來建立實體,然後釋放記憶體。這種傳統概念在 C++ 等 OOP 語言中仍然可以接受,但是不鼓勵使用。在 C++ 中,RAII 的概念使得在作用域內輕鬆分配和釋放資源成為可能。
新數量的有效期是物件的有效期,建構函式可以建立和分配記憶體給物件,而解構函式可以用來在完成後自動釋放記憶體。這使得 C++ 成為一種非常高效且使用者友好的語言。讓我們透過一個簡單的例子來理解這一點。
示例
#include <bits/stdc++.h> using namespace std; mutex m; void bad() { m.lock(); // acquire the mutex f(); // if f() throws an exception, the mutex is never released if (!everything_ok()) return; // early return, the mutex is never released m.unlock(); // if bad() reaches this statement, the mutex is released } void good(){ lock_guard<mutex> lk(m); // RAII class: mutex acquisition is initialization f(); // if f() throws an exception, the mutex is released if (!everything_ok()) return; // early return, the mutex is released } int main(){ good(); bad(); return 0; }
C++ 中的野指標
如果指標隨機指向記憶體中的任何地址,則該指標稱為野指標。當在程式中宣告指標但未將其初始化為指向地址值時,就會發生這種情況。野指標與普通指標不同,即它們也儲存記憶體地址,但指向未分配的記憶體或已釋放的資料值。
這些指標可能導致記憶體洩漏,這將在本文的後面部分討論。
示例
#include <bits/stdc++.h> using namespace std; int main() { int *ptr; //this pointer has been declared but not initialized //hence, it is a wild pointer cout<<*ptr<<endl; int a=11; ptr=&a; cout<<*ptr<<endl<<ptr<<endl; //once a value is declared, it becomes a normal pointer *ptr=10; cout<<*ptr<<endl<<ptr; return 0; }
輸出
-660944088 11 0x7ffcfb77825c 10 0x7ffcfb77825c
C++ 中的空指標
在早期版本的 C++ 中,NULL 將被定義為指向任何記憶體的 void 元素。允許將 NULL 轉換為int 或類似的資料型別,但在函式過載的情況下,空指標會引發錯誤。
自從C++ 11出現以來,NULL 已重新定義為nullptr,這是一種特殊的資料型別,只能用作指標來指向記憶體中不可用的地址。
因此,它可以在重新定義指標變數時充當指向任何位置的指標。與 NULL 不同,它不能隱式轉換為整數型別(如int或char),也不能與整數型別進行比較。因此,它解決了 NULL 的固有問題。
順便說一句,在新版本的 C++ 中,空指標之間可以進行比較,因此可以理解指標可以與bool資料型別進行比較。
示例
#include <bits/stdc++.h> using namespace std; int main() { //int ptr=nullptr; //this throws compiler error as it is not comparable to int //run the above line for illustration int *ptr=nullptr; if(ptr==nullptr) cout<<"true"; else cout<<"false"; return 0; }
輸出
true
C++ 中的記憶體洩漏
記憶體洩漏是許多計算裝置中的一個主要問題,因為編譯器在程式中可用的棧和堆記憶體是有限的且非常昂貴。當宣告新物件、使用新物件但未清除記憶體中的新物件時,就會發生記憶體洩漏。如果程式設計師忘記使用delete 操作或錯誤地使用它,就會發生這種情況。
記憶體洩漏有很大的缺點,因為空間隨著每個傳入的程序請求呈指數增長,新的程序必須分配新的記憶體空間,而不是清除不需要的記憶體。
給定的程式演示瞭如何在使用 C++ 的程式中發生記憶體洩漏。
示例
#include <bits/stdc++.h> using namespace std; void leak_func(){ int* p = new int(10); //using new() to declare a new object //no delete() operation return; } int main(){ leak_func(); return 0; }
可以透過釋放最初分配給new()物件的記憶體來避免這種情況。下面的程式說明了如何避免記憶體洩漏。
示例
#include <bits/stdc++.h> using namespace std; void leak_func(){ int* p = new int(10); //using new() to declare a new object delete(p); return; } int main(){ leak_func(); return 0; }
C++中的智慧指標
隨著C++中RAII和OOP概念的引入,包裝類也已在C++中引入。這些包裝類之一是智慧指標,它有助於確保沒有記憶體洩漏和錯誤的例項。
示例
#include <bits/stdc++.h> using namespace std; int main() { //int ptr=nullptr; //this throws compiler error as it is not comparable to int int *ptr=nullptr; if(ptr==nullptr) cout<<"true"; else cout<<"false"; return 0; }
輸出
true
C++中的Lambda表示式
從C++ 11開始,允許在C++中使用lambda表示式來解決行內函數,這些函式用於少量程式碼行,無需為函式命名和指定作用域。
語法
[ capture clause ] (parameters) -> return-type{ definition of method }
在這裡,返回型別由編譯器本身解析,無需指定函式的返回型別。但是,對於複雜的語句,需要指定返回型別才能使編譯器正常執行。
可以按以下方式捕獲外部變數:
- 按引用捕獲
- 按值捕獲
- 同時捕獲(混合捕獲)
用於捕獲變數的語法如下:
- [&]:按引用捕獲所有外部變數
- [=]:按值捕獲所有外部變數
- [a, &b]:按值捕獲a,按引用捕獲b
示例
#include <bits/stdc++.h> using namespace std; void printvector(vector<int> &v){ // lambda expression to print vector for_each(v.begin(), v.end(), [](int i){ std::cout << i << " "; }); cout << endl; } int main(){ vector<int> v; v.push_back(10); v.push_back(11); v.push_back(12); printvector(v); return 0; }
輸出
10 11 12