一、C++中的const
C++中的const限定符可以用於變量、函數參數、函數返回類型等多種情況。使用const限定符可以使代碼更加安全、簡潔、易於維護。
1、 const變量
const變量在定義後就不能被修改,這使得代碼更加安全。對於只讀變量,建議使用const限定符。
const int MAX_SIZE = 100; int main() { const int a = 10; a = 20; // error: assignment of read-only variable 'a' return 0; }
2、const函數參數
const函數參數可以避免函數內部無意義的變量修改,使得代碼更加簡潔和易於維護。
void foo(const int a) { a = 10; // error: assignment of read-only parameter 'a' }
3、const函數返回類型
const函數返回的變量不能被修改,使用const返回類型可以防止返回的數據在外部被意外修改。
const int& get_max(const int& a, const int& b) { return a > b ? a : b; }
二、C++中的STL容器
STL(Standard Template Libraries)是一個通用的C++標準庫,其中包含了很多現成的數據結構和算法。STL容器是STL庫中的一種數據結構,包括vector、list、set、map等。
1、vector
vector是一個動態的數組,可以存儲任意類型的數據。vector提供了類似數組的隨機訪問能力,並能夠動態地調整容量大小。
#include vector v; // 定義一個空的vector vector v(10); // 定義一個大小為10的vector,初始值都為0 v.push_back(1); // 在vector尾部插入一個元素1 v.pop_back(); // 從vector尾部刪除一個元素 int size = v.size();// 獲取vector中當前的元素個數
2、list
list是一個雙向鏈表,可以存儲任意類型的數據。list提供了類似數組的插入、刪除、移動等操作,但沒有隨機訪問能力。
#include list l; // 定義一個空的list l.push_back(1); // 在list尾部插入一個元素1 l.push_front(2); // 在list頭部插入一個元素2 l.pop_back(); // 從list尾部刪除一個元素 l.pop_front(); // 從list頭部刪除一個元素
3、set
set是一個集合,可以存儲任意類型的數據。set以排序的方式存儲數據,且每個元素僅出現一次。
#include set s; // 定義一個空的set s.insert(1); // 向set中插入元素1 s.insert(2); s.erase(2); // 刪除set中元素2
4、map
map是一個關聯數組,可以存儲任意類型的數據。map以排序的方式存儲數據,每個元素是一個鍵值對。
#include
三、C++中的多線程編程
C++11引入了多線程庫,可以更簡單地開發多線程應用。多線程編程可以提高程序的並發性能,但也會帶來一些問題。
1、使用多線程進行並行計算
多線程編程中常用的並發計算方法是線程池。線程池是一種預先分配了多個線程的程序結構,這些線程統一管理,循環執行任務,可有效節約線程創建和銷毀的開銷。
#include #include #include #include using namespace std; class ThreadPool { public: ThreadPool(int n) :stop_flag_(false) { for (int i = 0; i < n; i++) { threads_.push_back(thread(&ThreadPool::Process, this)); } } ~ThreadPool() { Stop(); for (auto& t : threads_) { t.join(); } } void AddTask(function f) { { unique_lock lock(mutex_); tasks_.push(f); } cv_.notify_one(); } void Stop() { { unique_lock lock(mutex_); stop_flag_ = true; } cv_.notify_all(); } private: void Process() { while (true) { function f; { unique_lock lock(mutex_); cv_.wait(lock, [this](){ return !tasks_.empty() || stop_flag_; }); if (stop_flag_) break; f = tasks_.front(); tasks_.pop(); } f(); } } bool stop_flag_; queue<function> tasks_; vector threads_; mutex mutex_; condition_variable cv_; }; int main() { ThreadPool pool(4); for (int i = 0; i < 10; i++) { pool.AddTask([i](){ cout << "Task " << i << " is running." << endl; }); } pool.Stop(); return 0; }
2、多線程帶來的問題
多線程編程會帶來一些問題,例如競態條件、死鎖、飢餓等。其中最常見的競態條件就是多個線程同時訪問同一份數據,導致數據不一致的問題。
避免競態條件的方法通常是在關鍵代碼段加鎖,使得同一時間只有一個線程能夠執行這段代碼。這樣雖然能解決競態條件問題,但也會帶來一些開銷,例如鎖的創建、銷毀、加鎖、解鎖等消耗都很大,同時也會降低並發性能。
3、C++11中的原子操作
原子操作是在不需要鎖的情況下實現同步的一種方式,能夠提高程序的並發性能。
例如,C++11中的atomic類型可以保證對T的操作都是原子的。
atomic cnt(0); void ThreadFunc() { for (int i = 0; i < 10000; i++) { cnt++; // 相當於cnt = cnt + 1,這裡的操作是原子的 } } int main() { vector v; for (int i = 0; i < 4; i++) { v.push_back(thread(ThreadFunc)); } for (int i = 0; i < 4; i++) { v[i].join(); } cout << cnt << endl; // 正確輸出:40000 return 0; }
C++11中還提供了一些其他的原子類型,例如std::atomic_flag、std::atomic_bool、std::atomic_int等。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/275736.html