大家好,我是⑩。

大家在学习C++或者QT的时候,总是会遇到内存泄漏的问题。就是如果忘记删除,或者删除的情况没有考虑清楚,容易造成悬挂指针(dangling pointer)或者说野指针(wild pointer)。

一:C++智能指针总类:shared_ptr unique_ptr weak_ptr。

1.shared_ptr:共享所有权指针,对资源做引用计数。

  智能指针定义

shared_ptr<int> p = make_shared<int>(1);
shared_ptr<int> p2(p);
shared_ptr<int> p3 = p;
1.1shared_ptr需要维护的信息有两部分
  1. 指向共享资源的指针。
  2. 引用计数等共享资源的控制信息——实现上是维护一个指向控制信息的指针。
1.2手撕shared_ptr智能指针
// 简化实现
template<typename T>
class SharedPtr {
    T* ptr;
    int* count;  // 引用计数
    
public:
    SharedPtr(T* p) : ptr(p), count(new int(1)) {}
    
    SharedPtr(const SharedPtr& other) 
        : ptr(other.ptr), count(other.count) {
        ++(*count);  // 增加引用计数
    }
    
    ~SharedPtr() {
        if (--(*count) == 0) {
            delete ptr;
            delete count;
        }
    }
};
1.3shared_ptr引发的循环引用问题
struct Father
{
    shared_ptr<Son> son_;
};

struct Son
{
    shared_ptr<Father> father_;
};

int main()
{
    auto father = make_shared<Father>();
    auto son = make_shared<Son>();

    father->son_ = son;
    son->father_ = father;

    return 0;
}

该部分代码会有内存泄漏问题。原因是
1.main 函数退出之前,Father 和 Son 对象的引用计数都是 2。
2.son 指针销毁,这时 Son 对象的引用计数是 1,father 指针销毁,这时 Father 对象的引用计数是 1。

1.4解决循环引用问题

3.由于两个智能指针的引用计数都不为0,导致循环引用的内存泄漏,这时就需要使用 weak_ptr。weak_ptr 并不拥有其指向的对象,也就是说,让 weak_ptr 指向 shared_ptr 所指向对象,对象的引用计数并不会增加。

struct Father
{
    shared_ptr<Son> son_;
};

struct Son
{
    weak_ptr<Father> father_;
};

int main()
{
    auto father = make_shared<Father>();
    auto son = make_shared<Son>();

    father->son_ = son;
    son->father_ = father;

    return 0;
}

2.unique_ptr:独占所有权指针,不可拷贝,只可引用。

2.1使用unique_ptr自动管理内存
std::unique_ptr<int> uptr = std::make_unique<int>(200);
    //...
    // 离开 uptr 的作用域的时候自动释放内存
2.2只可引用,不可拷贝问题
std::unique_ptr utr=std::make_unique<int> 200;
std::unique_ptr utr1=utr;//编译错误,std::unique_ptr<T> 是 move-only 的。
std::unique_ptr utr2=std::move(utr);
assert(uptr == nullptr);

3.weak_ptr:弱引用智能指针,不增加引用计数,用于解决循环引用问题。

3.1一个 weak_ptr 对象看做是 std::shared_ptr 对象管理的资源的观察者,它不影响共享资源的生命周期。

二:QT智能指针总类:QSharedPointer QScopedPointer QWeakPointer

1.QSharedpointer:类似于std::shared_ptr,使用引用计数实现共享所有权。

2.QScopedPointer:类似于std::uniqued_ptr,是独占所有权的。当指针离开作用域时,它指向的对象会被自动删除。不能用于容器

3.QScpoedPointer:似于std::weak_ptr,与QSharedPointer配合使用,解决循环引用问题。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐