当两个或多个对象相互引用时,如果使用shared_ptr来管理它们的内存,就可能会导致循环引用,从而导致内存泄漏。而使用weak_ptr可以避免这个问题,因为weak_ptr不会增加对象的引用计数,也不会阻止对象的销毁。

#include <iostream>
#include <vector>
#include <unordered_set>

template <typename T>
class shared_ptr {
private:
    T* ptr;
    int* ref_count;
    void release() {
        if (ref_count) {
            --(*ref_count);
            if (*ref_count == 0) {
                delete ptr;
                delete ref_count;
            }
            ptr = nullptr;
            ref_count = nullptr;
        }
    }

public:
    shared_ptr() : ptr(nullptr), ref_count(nullptr) {}
    shared_ptr(T* p) : ptr(p), ref_count(new int(1)) {}
    shared_ptr(T* p, int* ref) : ptr(p), ref_count(ref) {}
    shared_ptr(const shared_ptr& other) : ptr(other.ptr), ref_count(other.ref_count) {
        if (ref_count) {
            ++(*ref_count);
        }
    }
    ~shared_ptr() {
        release();
    }
    shared_ptr& operator=(const shared_ptr& other) {
        if (this != &other) {
            release();
            ptr = other.ptr;
            ref_count = other.ref_count;
            if (ref_count) {
                ++(*ref_count);
            }
        }
        return *this;
    }

    T* get() const {
        return ptr;
    }

    int use_count() const {
        return ref_count ? *ref_count : 0;
    }

    int* use_count_ptr() const {
        return ref_count;
    }
    void reset() {
        release();
    }

    void reset(T* p) {
        release();
        ptr = p;
        ref_count = new int(1);
    }

    T& operator*() const {
        return *ptr;
    }

    T* operator->() const {
        return ptr;
    }
};


template <typename T>
class weak_ptr {
private:
    T* ptr;
    int* ref_count;
public:
    weak_ptr() : ptr(nullptr), ref_count(nullptr) {}
    weak_ptr(const shared_ptr<T>& other) : ptr(other.get()), ref_count(other.use_count_ptr()) {}
    weak_ptr(const weak_ptr<T>& other) : ptr(other.get()), ref_count(other.use_count_ptr()) {}
    ~weak_ptr() {}

    bool expired() const {
        return ref_count == nullptr || *ref_count == 0;
    }

    shared_ptr<T> lock() const {
        if (expired()) {
            return shared_ptr<T>();
        } else {
            return shared_ptr<T>(ptr, ref_count);
        }
    }

    int* use_count_ptr() const {
        return ref_count;
    }

    T* get() const {
        return ptr;
    }

    int use_count() const {
        return ref_count ? *ref_count : 0;
    }
};

typedef shared_ptr<MyClass> MyClassPtr;
typedef weak_ptr<MyClass> MyClassWeakPtr;

class MyClass {
public:
    MyClass() {
        std::cout << "MyClass constructor" << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructor" << std::endl;
    }

    void setNext(const MyClassPtr& next) {
        next_ = next;
    }

    MyClassWeakPtr getNext() const {
        return next_;
    }

private:
    MyClassWeakPtr next_;
};

int main() {
    MyClassPtr obj1(new MyClass());
    MyClassPtr obj2(new MyClass());
    obj1->setNext(obj2);
    obj2->setNext(obj1);

    std::cout << "obj1.use_count() = " << obj1.use_count() << std::endl;
    std::cout << "obj2.use_count() = " << obj2.use_count() << std::endl;

    MyClassWeakPtr weak1 = obj1->getNext();
    MyClassWeakPtr weak2 = obj2->getNext();

    std::cout << "weak1.expired() = " << weak1.expired() << std::endl;
    std::cout << "weak2.expired() = " << weak2.expired() << std::endl;

    MyClassPtr next1 = weak1.lock();
    MyClassPtr next2 = weak2.lock();

    std::cout << "next1.use_count() = " << next1.use_count() << std::endl;
    std::cout << "next2.use_count() = " << next2.use_count() << std::endl;

    return 0;
}

在 weak_ptr 的构造函数中,我们可以将一个 shared_ptr 对象转换为 weak_ptr 对象,从而创建一个指向同一个对象的弱引用。在 lock 函数中,我们可以通过判断对象的引用计数是否为 0 来判断对象是否已经被销毁,如果对象已经被销毁,则返回一个空的 shared_ptr 对象,否则返回一个指向对象的 shared_ptr 对象。在 expired 函数中,我们可以通过判断对象的引用计数是否为 0 来判断对象是否已经被销毁。

··