完整的C++編程教程
目錄
- 開發環境配置
- C++知識體系
- 現代C++特性
- 設計模式
- 數據結構
- CMake項目構建
- 調試技巧
- 進階主題
- 學習資源
1. 開發環境配置
1.1 安裝編譯器
sudo apt-get install g++ build-essential
1.2 安裝構建工具
sudo apt-get install cmake
1.3 VS Code配置
- 安裝C++擴展
- 配置調試環境
- 安裝CMake Tools擴展
2. C++知識體系
2.1 基礎語法
#include <iostream>int main() {std::cout << "Hello World!" << std::endl;return 0;
}
2.2 面向對象編程
class MyClass {
public:MyClass() {}~MyClass() {}void print() {std::cout << "MyClass instance" << std::endl;}
};
3. 現代C++特性
3.1 自動類型推導
auto x = 5; // 自動推導為int
auto str = "hello"; // 自動推導為const char*
3.2 Lambda表達式
auto sum = [](int a, int b) { return a + b; };
std::cout << sum(3, 4) << std::endl; // 輸出7
4. 設計模式
4.1 單例模式
class Singleton {
private:Singleton() {}public:static Singleton& instance() {static Singleton instance;return instance;}
};
UML圖
+------------------+
| Singleton |
+------------------+
| - instance: static Singleton |
+------------------+
| + getInstance(): static Singleton& |
+------------------+
應用場景:
- 全局配置管理
- 日志系統
- 數據庫連接池
- 緩存系統
- 線程池
性能分析:
- 線程安全(C++11后static局部變量初始化是線程安全的)
- 延遲初始化
- 內存效率高
- 首次調用可能有輕微性能開銷
現代C++改進:
// 使用std::call_once確保線程安全
class ThreadSafeSingleton {
private:ThreadSafeSingleton() {}static std::once_flag initFlag;static std::unique_ptr<ThreadSafeSingleton> instance;public:static ThreadSafeSingleton& getInstance() {std::call_once(initFlag, []() {instance.reset(new ThreadSafeSingleton());});return *instance;}
};
4.1 單例模式
class Singleton {
private:Singleton() {}public:static Singleton& instance() {static Singleton instance;return instance;}
};
UML圖
+------------------+
| Singleton |
+------------------+
| - instance: static Singleton |
+------------------+
| + getInstance(): static Singleton& |
+------------------+
應用場景:
- 全局配置管理
- 日志系統
- 數據庫連接池
- 緩存系統
- 線程池
性能分析:
- 線程安全(C++11后static局部變量初始化是線程安全的)
- 延遲初始化
- 內存效率高
- 首次調用可能有輕微性能開銷
現代C++改進:
// 使用std::call_once確保線程安全
class ThreadSafeSingleton {
private:ThreadSafeSingleton() {}static std::once_flag initFlag;static std::unique_ptr<ThreadSafeSingleton> instance;public:static ThreadSafeSingleton& getInstance() {std::call_once(initFlag, []() {instance.reset(new ThreadSafeSingleton());});return *instance;}
};
4.2 工廠模式
class Product {
public:virtual ~Product() {}virtual void operation() = 0;
};class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA operation" << std::endl;}
};class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB operation" << std::endl;}
};class Factory {
public:virtual Product* createProduct() = 0;
};class ConcreteFactoryA : public Factory {
public:Product* createProduct() override {return new ConcreteProductA();}
};class ConcreteFactoryB : public Factory {
public:Product* createProduct() override {return new ConcreteProductB();}
};
UML圖
+------------------+ +------------------+
| Product |<------| ConcreteProductA |
+------------------+ +------------------+
| + operation(): virtual | +------------------+
+------------------+ | ConcreteProductB |+------------------++------------------+ +------------------+
| Factory |<------| ConcreteFactoryA |
+------------------+ +------------------+
| + createProduct(): virtual | +------------------+
+------------------+ | ConcreteFactoryB |+------------------+
應用場景:
- 需要創建多種相似對象
- 對象創建邏輯復雜
- 需要解耦客戶端和具體產品類
- 需要動態擴展產品類型
- 需要集中管理對象創建
性能分析:
- 虛函數調用開銷
- 對象創建成本
- 內存分配開銷
現代C++改進:
// 使用智能指針避免內存泄漏
template<typename T>
std::unique_ptr<Product> createProduct() {return std::make_unique<T>();
}// 使用模板工廠
template<typename ProductType>
class TemplateFactory {
public:std::unique_ptr<Product> create() {return std::make_unique<ProductType>();}
};// 使用lambda工廠
auto productFactory = [](auto&&... args) {return std::make_unique<Product>(std::forward<decltype(args)>(args)...);
};
class Product {
public:virtual ~Product() {}virtual void operation() = 0;
};class ConcreteProductA : public Product {
public:void operation() override {std::cout << "ConcreteProductA operation" << std::endl;}
};class ConcreteProductB : public Product {
public:void operation() override {std::cout << "ConcreteProductB operation" << std::endl;}
};class Factory {
public:virtual Product* createProduct() = 0;
};class ConcreteFactoryA : public Factory {
public:Product* createProduct() override {return new ConcreteProductA();}
};class ConcreteFactoryB : public Factory {
public:Product* createProduct() override {return new ConcreteProductB();}
};
UML圖
+------------------+ +------------------+
| Product |<------| ConcreteProductA |
+------------------+ +------------------+
| + operation(): virtual | +------------------+
+------------------+ | ConcreteProductB |+------------------++------------------+ +------------------+
| Factory |<------| ConcreteFactoryA |
+------------------+ +------------------+
| + createProduct(): virtual | +------------------+
+------------------+ | ConcreteFactoryB |+------------------+
應用場景:
- 需要創建多種相似對象
- 對象創建邏輯復雜
- 需要解耦客戶端和具體產品類
- 需要動態擴展產品類型
- 需要集中管理對象創建
性能分析:
- 虛函數調用開銷
- 對象創建成本
- 內存分配開銷
現代C++改進:
// 使用智能指針避免內存泄漏
template<typename T>
std::unique_ptr<Product> createProduct() {return std::make_unique<T>();
}// 使用模板工廠
template<typename ProductType>
class TemplateFactory {
public:std::unique_ptr<Product> create() {return std::make_unique<ProductType>();}
};// 使用lambda工廠
auto productFactory = [](auto&&... args) {return std::make_unique<Product>(std::forward<decltype(args)>(args)...);
};
4.3 觀察者模式
#include <vector>
#include <algorithm>
#include <memory>
#include <mutex>
#include <functional>
#include <unordered_map>
#include <any>// 基礎觀察者接口
class Observer {
public:virtual ~Observer() = default;virtual void update(const std::string& message) = 0;
};// 主題/被觀察者
class Subject {
private:std::vector<std::weak_ptr<Observer>> observers;std::mutex mtx;public:// 線程安全的觀察者注冊void attach(std::shared_ptr<Observer> obs) {std::lock_guard<std::mutex> lock(mtx);observers.emplace_back(obs);}// 線程安全的觀察者注銷void detach(std::shared_ptr<Observer> obs) {std::lock_guard<std::mutex> lock(mtx);observers.erase(std::remove_if(observers.begin(), observers.end(),[&obs](const std::weak_ptr<Observer>& weakObs) {return weakObs.expired() || weakObs.lock() == obs;}),observers.end());}// 線程安全的通知所有觀察者void notify(const std::string& message) {std::lock_guard<std::mutex> lock(mtx);for (auto it = observers.begin(); it != observers.end(); ) {if (auto obs = it->lock()) {obs->update(message);++it;} else {it = observers.erase(it);}}}
};// 具體觀察者實現
class ConcreteObserver : public Observer {std::string name;
public:explicit ConcreteObserver(std::string name) : name(std::move(name)) {}void update(const std::string& message) override {std::cout << "Observer " << name << " received: " << message << std::endl;}
};// 現代C++改進:使用std::function和lambda
class Observable {std::vector<std::function<void(const std::string&)>> observers;std::mutex mtx;public:void subscribe(std::function<void(const std::string&)> observer) {std::lock_guard<std::mutex> lock(mtx);observers.push_back(observer);}void unsubscribe(std::function<void(const std::string&)> observer) {std::lock_guard<std::mutex> lock(mtx);observers.erase(std::remove(observers.begin(), observers.end(), observer),observers.end());}void notify(const std::string& message) {std::lock_guard<std::mutex> lock(mtx);for (auto& observer : observers) {observer(message);}}
};// C++20 協程改進
struct EventAwaiter {Observable& observable;std::string message;bool ready = false;EventAwaiter(Observable& obs) : observable(obs) {observable.subscribe([this](const std::string& msg) {message = msg;ready = true;});}bool await_ready() const { return ready; }void await_suspend(std::coroutine_handle<>) {}std::string await_resume() { return message; }
};// 使用示例
Task asyncEventListener(Observable& observable) {auto message = co_await EventAwaiter(observable);std::cout << "Received async message: " << message << std::endl;
}// 使用示例
int main() {// 傳統觀察者模式使用auto subject = std::make_shared<Subject>();auto observer1 = std::make_shared<ConcreteObserver>("Observer1");auto observer2 = std::make_shared<ConcreteObserver>("Observer2");subject->attach(observer1);subject->attach(observer2);subject->notify("Hello World!");// 現代C++風格使用Observable modernSubject;auto callback = [](const std::string& msg) {std::cout << "Lambda observer received: " << msg << std::endl;};modernSubject.subscribe(callback);modernSubject.notify("Modern C++ message");return 0;
}
UML圖
+------------------+ +------------------+
| Subject |<>----->| Observer |
+------------------+ +------------------+
| + attach(Observer) | | + update(): virtual |
| + detach(Observer) | +------------------+
| + notify() | ^
+------------------+ ||+------------------+| ConcreteObserver |+------------------+
應用場景:
- 事件驅動系統
- GUI組件交互
- 發布-訂閱系統
- 狀態監控
- 數據同步
- 微服務架構中的事件通知
- 物聯網設備狀態更新
- 金融交易實時監控
- 游戲引擎事件處理
- 分布式系統狀態同步
性能優化:
- 使用weak_ptr避免內存泄漏
- 異步通知減少阻塞
- 批量通知優化
- 線程安全實現
- 觀察者去重
- 使用對象池管理觀察者
- 事件過濾減少不必要通知
- 按優先級分組通知
- 使用無鎖數據結構優化高頻事件
- 事件合并減少通知頻率
現代C++改進:
// 使用信號槽庫
#include <boost/signals2.hpp>struct Event {void operator()() {std::cout << "Event triggered" << std::endl;}
};boost::signals2::signal<void()> signal;
signal.connect(Event());
signal();// 使用std::function和lambda
class Observable {std::vector<std::function<void(const std::string&)>> observers;
public:void subscribe(std::function<void(const std::string&)> observer) {observers.push_back(observer);}void notify(const std::string& message) {for (auto& observer : observers) {observer(message);}}
};
5. 數據結構
5.1 鏈表實現
struct Node {int data;Node* next;
};class LinkedList {Node* head;
public:void insert(int data) {Node* newNode = new Node{data, head};head = newNode;}
};
6. CMake項目構建
cmake_minimum_required(VERSION 3.10)
project(MyProject)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)add_executable(myapp main.cpp)
7. 調試技巧
- 使用gdb調試
- 打印變量值
- 設置斷點
- 查看調用棧
8. 進階主題
8.1 模板元編程
// C++20 概念(Concepts)示例
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;template<Numeric T>
T square(T x) {return x * x;
}// 編譯期字符串處理
constexpr size_t string_length(const char* str) {return *str ? 1 + string_length(str + 1) : 0;
}// C++23 編譯期反射提案示例
/*
struct Person {std::string name;int age;
};constexpr auto members = reflect(Person);
static_assert(members.size() == 2);
static_assert(members[0].name == "name");
*/
應用場景:
- 編譯期類型檢查
- 領域特定嵌入式語言(EDSL)
- 序列化/反序列化框架
- 高性能數學庫
- 編譯期數據結構
性能優化技巧:
- 使用constexpr if減少實例化
- 模板特化優化熱點路徑
- 使用變量模板緩存中間結果
- 編譯期字符串哈希優化查找
- 使用折疊表達式簡化可變參數模板
template<int N>
struct Factorial {static const int value = N * Factorial<N-1>::value;
};template<>
struct Factorial<0> {static const int value = 1;
};// 編譯期斷言
static_assert(Factorial<5>::value == 120, "Factorial calculation error");
現代C++改進(C++11/14/17):
// C++11 constexpr函數
constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);
}// C++14 constexpr函數改進
constexpr auto factorial14(auto n) {decltype(n) result = 1;for (decltype(n) i = 1; i <= n; ++i) {result *= i;}return result;
}// C++17 變量模板
template<auto N>
constexpr auto factorial17 = N * factorial17<N-1>;template<>
constexpr auto factorial17<0> = 1;// C++20 consteval函數
consteval int compile_time_factorial(int n) {return n <= 1 ? 1 : n * compile_time_factorial(n - 1);
}
應用場景:
- 編譯期計算
- 類型特征檢查
- 代碼生成
- 算法優化
- 領域特定語言(DSL)
性能分析:
- 零運行時開銷
- 增加編譯時間
- 可能增加二進制大小
高級技巧:
// SFINAE (Substitution Failure Is Not An Error)
template<typename T>
auto print_type_info(const T& t) -> decltype(t.toString(), void()) {std::cout << t.toString() << std::endl;
}template<typename T>
auto print_type_info(const T& t) -> decltype(t.to_string(), void()) {std::cout << t.to_string() << std::endl;
}template<typename T>
auto print_type_info(const T& t) -> decltype(std::cout << t, void()) {std::cout << t << std::endl;
}// 類型特征
template<typename T>
struct is_pointer {static constexpr bool value = false;
};template<typename T>
struct is_pointer<T*> {static constexpr bool value = true;
};// 使用if constexpr (C++17)
template<typename T>
auto process(const T& t) {if constexpr (is_pointer<T>::value) {std::cout << "Pointer to " << *t << std::endl;} else {std::cout << "Value " << t << std::endl;}
}
8.2 并發編程
#include <thread>
#include <iostream>
#include <mutex>
#include <latch>
#include <barrier>
#include <semaphore>// C++20 新特性示例
void concurrent_operations() {// std::latch 一次性屏障std::latch work_done(3);// std::barrier 可重用屏障std::barrier sync_point(3);// std::counting_semaphore 信號量std::counting_semaphore<10> sem(3);auto worker = [&](int id) {std::cout << "Worker " << id << " started" << std::endl;// 模擬工作std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));// 使用信號量sem.acquire();std::cout << "Worker " << id << " acquired semaphore" << std::endl;sem.release();// 到達同步點work_done.count_down();sync_point.arrive_and_wait();std::cout << "Worker " << id << " completed" << std::endl;};std::jthread t1(worker, 1);std::jthread t2(worker, 2);std::jthread t3(worker, 3);work_done.wait();std::cout << "All workers finished initial phase" << std::endl;
}#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
#include <future>
#include <condition_variable>
#include <atomic>
#include <queue>// 基本線程同步
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker_thread() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return ready; });std::cout << "Worker thread is processing data" << std::endl;
}// 線程安全隊列
template<typename T>
class ThreadSafeQueue {std::queue<T> queue;mutable std::mutex mtx;std::condition_variable cv;public:void push(T value) {std::lock_guard<std::mutex> lock(mtx);queue.push(std::move(value));cv.notify_one();}bool try_pop(T& value) {std::lock_guard<std::mutex> lock(mtx);if (queue.empty()) return false;value = std::move(queue.front());queue.pop();return true;}void wait_and_pop(T& value) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this]{ return !queue.empty(); });value = std::move(queue.front());queue.pop();}
};// 原子操作
std::atomic<int> counter(0);void increment_atomic() {for (int i = 0; i < 1000; ++i) {++counter;}
}int main() {// 基本線程示例std::thread worker(worker_thread);{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();worker.join();// 線程池示例const unsigned num_threads = std::thread::hardware_concurrency();std::vector<std::thread> threads;// 創建線程池工作函數auto worker = [](int id) {std::cout << "Thread " << id << " 開始工作" << std::endl;// 模擬工作負載std::this_thread::sleep_for(std::chrono::milliseconds(100));std::cout << "Thread " << id << " 完成工作" << std::endl;};// 啟動所有工作線程for (unsigned i = 0; i < num_threads; ++i) {threads.emplace_back(worker, i);}// 等待所有線程完成for (auto& t : threads) {if (t.joinable()) {t.join();}}std::cout << "所有線程任務已完成" << std::endl;
8.3 內存管理
#include <memory>
#include <memory_resource>
#include <vector>// 內存對齊分配示例 (C++17)
template<typename T>
struct AlignedAllocator {using value_type = T;explicit AlignedAllocator(size_t alignment = alignof(T)) : alignment(alignment) {if (alignment & (alignment - 1)) {throw std::invalid_argument("Alignment must be power of two");}}template<typename U>AlignedAllocator(const AlignedAllocator<U>& other) noexcept : alignment(other.alignment) {}[[nodiscard]] T* allocate(size_t n) {if (n > std::numeric_limits<size_t>::max() / sizeof(T)) {throw std::bad_alloc();}size_t size = n * sizeof(T);void* ptr = std::aligned_alloc(alignment, size);if (!ptr) {throw std::bad_alloc();}return static_cast<T*>(ptr);}void deallocate(T* p, size_t n) noexcept {std::free(p);}bool operator==(const AlignedAllocator&) const noexcept { return true; }bool operator!=(const AlignedAllocator&) const noexcept { return false; }size_t alignment;
};// 使用示例
std::vector<int, AlignedAllocator<int>> aligned_vec(AlignedAllocator<int>(64));// 自定義內存池分配器 (C++11)
template<typename T>
class PoolAllocator {struct Block {Block* next;};Block* freeList = nullptr;public:using value_type = T;using propagate_on_container_copy_assignment = std::true_type;using propagate_on_container_move_assignment = std::true_type;using propagate_on_container_swap = std::true_type;explicit PoolAllocator(size_t poolSize = 1024) {if (poolSize == 0) {throw std::invalid_argument("Pool size must be positive");}// 預分配內存池freeList = static_cast<Block*>(::operator new(poolSize * sizeof(T)));// 初始化空閑鏈表Block* current = freeList;for (size_t i = 0; i < poolSize - 1; ++i) {current->next = reinterpret_cast<Block*>(reinterpret_cast<char*>(current) + sizeof(T));current = current->next;}current->next = nullptr;}PoolAllocator(const PoolAllocator&) = delete;PoolAllocator& operator=(const PoolAllocator&) = delete;[[nodiscard]] T* allocate(size_t n) {if (n != 1 || !freeList) {throw std::bad_alloc();}Block* block = freeList;freeList = freeList->next;return reinterpret_cast<T*>(block);}void deallocate(T* p, size_t n) noexcept {if (n != 1 || !p) return;Block* block = reinterpret_cast<Block*>(p);block->next = freeList;freeList = block;}template<typename U>struct rebind {using other = PoolAllocator<U>;};
};// 使用示例
std::vector<int, PoolAllocator<int>> vec(PoolAllocator<int>(100));// 現代C++內存管理特性
/*
1. 智能指針 (C++11):- std::unique_ptr: 獨占所有權- std::shared_ptr: 共享所有權- std::weak_ptr: 打破循環引用2. 內存資源 (C++17):- std::pmr::memory_resource- std::pmr::polymorphic_allocator- 內置內存資源 (monotonic, pool, synchronized)3. 垃圾回收支持 (C++11):- std::declare_reachable- std::undeclare_reachable- std::declare_no_pointers- std::undeclare_no_pointers4. 內存模型 (C++11):- std::atomic- 內存順序約束- 線程安全保證
*/
現代C++內存管理特性:
1. 內存資源(Memory Resources)
```cpp
class MonotonicResource : public std::pmr::memory_resource {void* current = nullptr;size_t remaining = 0;protected:void* do_allocate(size_t bytes, size_t alignment) override {// 簡單線性分配實現void* p = std::align(alignment, bytes, current, remaining);if (!p) throw std::bad_alloc();current = static_cast<char*>(p) + bytes;remaining -= bytes;return p;}void do_deallocate(void*, size_t, size_t) override {}bool do_is_equal(const memory_resource& other) const noexcept override {return this == &other;}
};
- 多態內存資源
- 棧分配器(stack allocator)
- 內存池優化
性能分析工具:
- Valgrind
- AddressSanitizer
- MemorySanitizer
- ThreadSanitizer
- 自定義分配器性能測試方法
#include <memory>class Resource {
public:Resource() { std::cout << "Resource acquired" << std::endl; }~Resource() { std::cout << "Resource released" << std::endl; }
};int main() {// 使用智能指針自動管理內存auto ptr = std::make_unique<Resource>();// 移動語義示例auto ptr2 = std::move(ptr); // 所有權轉移// 共享所有權auto shared = std::make_shared<Resource>();return 0;
}
現代C++特性:
- 移動語義(std::move)
- 完美轉發
- RAII原則
9. 學習資源
- 《C++ Primer》
- 《Effective C++》
- cppreference.com
- Stack Overflow C++社區