智能指針是C++11引入的重要特性,用于自動管理動態分配的內存,防止內存泄漏。下面介紹幾種高級智能指針編程實例。
1. 共享所有權模式 (shared_ptr)
循環引用問題及解決方案
#include <memory> #include <iostream>class B; // 前向聲明class A { public:std::shared_ptr<B> b_ptr;~A() { std::cout << "A destroyed\n"; } };class B { public:std::shared_ptr<A> a_ptr; // 這里會導致循環引用~B() { std::cout << "B destroyed\n"; } };void circularReferenceProblem() {auto a = std::make_shared<A>();auto b = std::make_shared<B>();a->b_ptr = b;b->a_ptr = a; // 循環引用// 離開作用域時,a和b不會被銷毀 }// 使用weak_ptr解決循環引用 class B_fixed;class A_fixed { public:std::shared_ptr<B_fixed> b_ptr;~A_fixed() { std::cout << "A_fixed destroyed\n"; } };class B_fixed { public:std::weak_ptr<A_fixed> a_ptr; // 使用weak_ptr打破循環~B_fixed() { std::cout << "B_fixed destroyed\n"; } };void circularReferenceSolution() {auto a = std::make_shared<A_fixed>();auto b = std::make_shared<B_fixed>();a->b_ptr = b;b->a_ptr = a; // weak_ptr不會增加引用計數// 離開作用域時,a和b會被正確銷毀 }
2. 獨占所有權模式 (unique_ptr)
工廠模式應用
#include <memory> #include <iostream>class Base { public:virtual void doSomething() = 0;virtual ~Base() = default; };class Derived1 : public Base { public:void doSomething() override {std::cout << "Derived1 doing something\n";} };class Derived2 : public Base { public:void doSomething() override {std::cout << "Derived2 doing something\n";} };enum class ProductType { TYPE1, TYPE2 };std::unique_ptr<Base> createProduct(ProductType type) {switch(type) {case ProductType::TYPE1: return std::make_unique<Derived1>();case ProductType::TYPE2: return std::make_unique<Derived2>();default: return nullptr;} }void factoryPatternExample() {auto product1 = createProduct(ProductType::TYPE1);auto product2 = createProduct(ProductType::TYPE2);product1->doSomething();product2->doSomething();// unique_ptr會自動管理內存 }
3. 弱引用模式 (weak_ptr)
緩存系統實現
#include <memory> #include <unordered_map> #include <iostream>class ExpensiveResource { public:ExpensiveResource(int id) : id(id) {std::cout << "Creating resource " << id << "\n";}~ExpensiveResource() {std::cout << "Destroying resource " << id << "\n";}void use() {std::cout << "Using resource " << id << "\n";} private:int id; };class ResourceCache { public:std::shared_ptr<ExpensiveResource> getResource(int id) {std::shared_ptr<ExpensiveResource> res;auto it = cache.find(id);if (it != cache.end()) {res = it->second.lock(); // 嘗試從weak_ptr獲取shared_ptr}if (!res) {res = std::make_shared<ExpensiveResource>(id);cache[id] = res; // 存儲weak_ptr}return res;}size_t size() const { return cache.size(); }private:std::unordered_map<int, std::weak_ptr<ExpensiveResource>> cache; };void cacheExample() {ResourceCache cache;{auto res1 = cache.getResource(1);auto res2 = cache.getResource(2);res1->use();res2->use();std::cout << "Cache size: " << cache.size() << "\n";}// 資源已釋放,但緩存中仍有weak_ptrstd::cout << "Cache size after resources out of scope: " << cache.size() << "\n";// 再次獲取資源1,會創建新實例auto res1_again = cache.getResource(1);res1_again->use(); }
4. 自定義刪除器
文件指針管理
#include <memory> #include <cstdio>void fileDeleter(FILE* file) {if (file) {std::fclose(file);std::cout << "File closed\n";} } void customDeleterExample() {// 使用自定義刪除器管理文件指針std::unique_ptr<FILE, decltype(&fileDeleter)> filePtr(std::fopen("example.txt", "w"), &fileDeleter);if (filePtr) {std::fputs("Hello, world!", filePtr.get());}// 離開作用域時自動調用fileDeleter關閉文件 }
5. 多態與智能指針
多態對象管理
#include <memory> #include <vector> #include <iostream>class Animal { public:virtual void speak() const = 0;virtual ~Animal() = default; };class Dog : public Animal { public:void speak() const override {std::cout << "Woof!\n";} };class Cat : public Animal { public:void speak() const override {std::cout << "Meow!\n";} };void polymorphismExample() {std::vector<std::unique_ptr<Animal>> animals;animals.push_back(std::make_unique<Dog>());animals.push_back(std::make_unique<Cat>());for (const auto& animal : animals) {animal->speak();}// unique_ptr會自動調用正確的析構函數 }
6. 共享指針與弱指針結合
觀察者模式實現
#include <memory> #include <vector> #include <iostream> #include <algorithm>class Observer;class Subject { public:void attach(std::weak_ptr<Observer> observer) {observers.push_back(observer);}void notifyAll();private:std::vector<std::weak_ptr<Observer>> observers; };class Observer : public std::enable_shared_from_this<Observer> { public:Observer(std::shared_ptr<Subject> subject) : subject(subject) {subject->attach(weak_from_this());}virtual void update() = 0;virtual ~Observer() = default;protected:std::shared_ptr<Subject> subject; };void Subject::notifyAll() {for (auto it = observers.begin(); it != observers.end(); ) {if (auto observer = it->lock()) {observer->update();++it;} else {it = observers.erase(it);}} }class ConcreteObserver : public Observer { public:using Observer::Observer;void update() override {std::cout << "Observer notified!\n";} };void observerPatternExample() {auto subject = std::make_shared<Subject>();auto observer1 = std::make_shared<ConcreteObserver>(subject);auto observer2 = std::make_shared<ConcreteObserver>(subject);subject->notifyAll();// 當observer超出作用域時,weak_ptr會自動失效 }
7. 智能指針與多線程
線程安全共享數據
#include <memory> #include <thread> #include <vector> #include <mutex> #include <iostream>class ThreadSafeData { public:void add(int value) {std::lock_guard<std::mutex> lock(mutex);data.push_back(value);}void print() const {std::lock_guard<std::mutex> lock(mutex);for (int val : data) {std::cout << val << " ";}std::cout << "\n";}private:mutable std::mutex mutex;std::vector<int> data; };void worker(std::shared_ptr<ThreadSafeData> data, int id) {for (int i = 0; i < 5; ++i) {data->add(id * 100 + i);} }void threadSafeExample() {auto data = std::make_shared<ThreadSafeData>();std::vector<std::thread> threads;for (int i = 0; i < 3; ++i) {threads.emplace_back(worker, data, i + 1);}for (auto& t : threads) {t.join();}data->print(); }
8. 智能指針與STL容器
容器中存儲智能指針
#include <memory> #include <vector> #include <iostream>class Item { public:Item(int id) : id(id) {std::cout << "Item " << id << " created\n";}~Item() {std::cout << "Item " << id << " destroyed\n";}void use() {std::cout << "Using item " << id << "\n";} private:int id; };void stlContainerExample() {std::vector<std::shared_ptr<Item>> items;items.push_back(std::make_shared<Item>(1));items.push_back(std::make_shared<Item>(2));items.push_back(std::make_shared<Item>(3));// 復制智能指針會增加引用計數auto item2 = items[1];for (const auto& item : items) {item->use();}// 當items和item2超出作用域時,Item對象會被正確銷毀 }
這些實例展示了C++智能指針在各種場景下的高級應用,包括內存管理、設計模式實現、多線程編程等。合理使用智能指針可以顯著提高代碼的安全性和可維護性。