智能指针是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_ptr
std::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++智能指针在各种场景下的高级应用,包括内存管理、设计模式实现、多线程编程等。合理使用智能指针可以显著提高代码的安全性和可维护性。