当两个或多个对象相互引用时,如果使用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 来判断对象是否已经被销毁。··
No comments yet.