C++ 使用智能指针会出现什么问题?怎么解决?

 6个月前     4  

文章目录

智能指针可能出现的问题:循环引用

在如下例子中定义了两个类 Parent、Child,在两个类中分别定义另一个类的对象的共享指针,由于在程序结束后,两个指针相互指向对方的内存空间,导致内存无法释放。

#include <iostream>
#include <memory>

using namespace std;

class Child;
class Parent;

class Parent {
 private:
  shared_ptr<Child> ChildPtr;

 public:
  void setChild(shared_ptr<Child> child) { this->ChildPtr = child; }

  void doSomething() {
    if (this->ChildPtr.use_count()) {
    }
  }

  ~Parent() {}
};

class Child {
 private:
  shared_ptr<Parent> ParentPtr;

 public:
  void setPartent(shared_ptr<Parent> parent) { this->ParentPtr = parent; }
  void doSomething() {
    if (this->ParentPtr.use_count()) {
    }
  }
  ~Child() {}
};

int main() {
  weak_ptr<Parent> wpp;
  weak_ptr<Child> wpc;
  {
    shared_ptr<Parent> p(new Parent);
    shared_ptr<Child> c(new Child);
    p->setChild(c);
    c->setPartent(p);
    wpp = p;
    wpc = c;
    cout << p.use_count() << endl;  // 2
    cout << c.use_count() << endl;  // 2
  }
  cout << wpp.use_count() << endl;  // 1
  cout << wpc.use_count() << endl;  // 1
  return 0;
}

循环引用的解决方法: weak_ptr

循环引用:该被调用的析构函数没有被调用,从而出现了内存泄漏。

weak_ptr 对被 shared_ptr 管理的对象存在非拥有性(弱)引用,在访问所引用的对象前必须先转化为 shared_ptr;

weak_ptr 用来打断 shared_ptr 所管理对象的循环引用问题,若这种环被孤立(没有指向环中的外部共享指针),shared_ptr 引用计数无法抵达 0,内存被泄露;令环中的指针之一为弱指针可以避免该情况;

weak_ptr 用来表达临时所有权的概念,当某个对象只有存在时才需要被访问,而且随时可能被他人删除,可以用 weak_ptr 跟踪该对象;需要获得所有权时将其转化为 shared_ptr,此时如果原来的 shared_ptr 被销毁,则该对象的生命期被延长至这个临时的 shared_ptr 同样被销毁。

#include <iostream>
#include <memory>

using namespace std;

class Child;
class Parent;

class Parent {
 private:
  // shared_ptr<Child> ChildPtr;
  weak_ptr<Child> ChildPtr;

 public:
  void setChild(shared_ptr<Child> child) { this->ChildPtr = child; }

  void doSomething() {
    // new shared_ptr
    if (this->ChildPtr.lock()) {
    }
  }

  ~Parent() {}
};

class Child {
 private:
  shared_ptr<Parent> ParentPtr;

 public:
  void setPartent(shared_ptr<Parent> parent) { this->ParentPtr = parent; }
  void doSomething() {
    if (this->ParentPtr.use_count()) {
    }
  }
  ~Child() {}
};

int main() {
  weak_ptr<Parent> wpp;
  weak_ptr<Child> wpc;
  {
    shared_ptr<Parent> p(new Parent);
    shared_ptr<Child> c(new Child);
    p->setChild(c);
    c->setPartent(p);
    wpp = p;
    wpc = c;
    cout << p.use_count() << endl;  // 2
    cout << c.use_count() << endl;  // 1
  }
  cout << wpp.use_count() << endl;  // 0
  cout << wpc.use_count() << endl;  // 0
  return 0;
}

暂无评论

暂无评论...