cpp_2_6_智能指针_1_shared_ptr

  1. Overview
  2. shared_ptr 实现内存共用
  3. shared_ptr 实现自动释放内存

Overview

1.shared_ptr 内存共用指针
2.shared_ptr 实现自动释放内存

shared_ptr 实现内存共用

1.shared_ptr 就是共享内存的指针, 使得多个 shared_ptr 可以共同使用同一块堆内存; 在实现上, 使用的是引用计数机制, 即: 有 1 个 指向的指针放弃了堆内存的使用权, 发生引用计数-1, 也不会影响其他指向同一块内存的 shared_ptr 指针; 只有引用计数为 0 时, 堆内存才会被自动释放; 例如我们有三个 shared_ptr p1/p2/p3 指向同一个 Ojbect

shared_ptr p1 -> Ojbect
shared_ptr p2 -> Ojbect
shared_ptr p3 -> Ojbect

这时候这个 Object 引用计数为 3, 当指向 Object 为 0 的时候, 程序就会自动释放这个 Object, 省去我们手动 delete 的烦恼

2.初始化 shared_ptr 有两类方法:
(i). 使用 make_shared 来初始化, 推荐使用这种方法去初始化, 因为效率更高且在 C++17 之前也更安全
(ii). 使用 new 关键字来初始化

初始化完之后, 就能像使用普通指针一样使用指针了;

#include <memory>
#include <iostream>

using namespace std;

int main() {
  shared_ptr<int> p = make_shared<int>(128);  // 1.make_shared 初始化 shared_ptr
  shared_ptr<int> p0{make_shared<int>(64)};   // 1.make_shared 初始化 shared_ptr
  shared_ptr<int> p1{new int(32)};            // 2.new 初始化 shared_tpr
  shared_ptr<int> p2(new int(16));            // 2.new 初始化 shared_tpr
  cout << *p << endl;
  cout << *p0 << endl;
  cout << *p1 << endl;
  cout << *p2 << endl;

  shared_ptr<int> p3;                         // 使用多个 shared_ptr 指向同一个object
  p3 = p;
  cout << *p3 << endl;
  return 0;
}

shared_ptr 实现自动释放内存

通过一个例子去理解 shared_ptr 如何通过计数自动地创建和释放内存, 这里涉及到调用两个函数

shared_ptr<int> p = make_shared<int>();
p.use_count();  // 返回当前 shared_ptr 指向相同的所有 shared_ptr 对象的数量;
p.reset();      // 函数没有实参数时, 该函数会使当前 shared_ptr 所指堆内存的引用计数减 1, 同时将当前对象重置为一个空指针
#include <iostream>
#include <memory>

using namespace std;

int main() {
  shared_ptr<int> p1(new int(10));
  cout << "p1.use_count()=" << p1.use_count() << endl;
  shared_ptr<int> p2(p1);
  cout << "*p2=" << *p2 << endl;
  cout << "p1.use_count()=" << p1.use_count() << endl;
  p1.reset(); // 引用计数减1, p1为空指针
  if (p1) {
    cout << "p1 is not nullptr" << endl;
  } else {
    cout << "p1 is nullptr" << endl;
  }
  cout << "p1.use_count()=" << p1.use_count() << endl;
  // 以上操作, 并不会影响 p2
  cout << "*p2=" << *p2 << endl;
  // 判断当前和 p2 同指向的智能指针共有多少个
  cout << "p2.use_count()=" << p2.use_count() << endl;
  return 0;
}

输出结果

p1.use_count()=1
*p2=10
p1.use_count()=2
p1 is nullptr
p1.use_count()=0
*p2=10
p2.use_count()=1

再引入一个 oop 的例子感受下 shared_ptr

#include <memory>
#include <iostream>
using namespace std;

class Ball {
 public:
  Ball() {
    cout << "A ball appears." << endl;
  }
  ~Ball() {
    cout << "A ball disappears." << endl;
  }
  void Bounce() {
    cout << "A ball jumps." << endl;
  }
};

int main () {
  shared_ptr<Ball> p = make_shared<Ball>();
  cout << "p.use_count()=" << p.use_count() << endl;
  shared_ptr<Ball> p2 = p;
  cout << "p.use_count()=" << p.use_count() << " p2.use_count()=" << p2.use_count() << endl;
  shared_ptr<Ball> p3 = p;
  cout << "p.use_count()=" << p.use_count() << " p2.use_count()=" << p2.use_count() << " p3.use_count()=" << p2.use_count() << endl;
  p.reset();
  cout << "after p.reset() p.use_count()=" << p.use_count() << " p2.use_count()=" << p2.use_count() << " p3.use_count()=" << p3.use_count() << endl;
  p2.reset();
  cout << "after p2.reset() p.use_count()=" << p.use_count() << " p2.use_count()=" << p2.use_count() << " p3.use_count()=" << p3.use_count() << endl;
  p3.reset();
  cout << "after p3.reset() p.use_count()=" << p.use_count() << " p2.use_count()=" << p2.use_count() << " p3.use_count()=" << p3.use_count() << endl;
  return 0;
}

输出结果

A ball appears.
p.use_count()=1
p.use_count()=2 p2.use_count()=2
p.use_count()=3 p2.use_count()=3 p3.use_count()=3
after p.reset() p.use_count()=0 p2.use_count()=2 p3.use_count()=2
after p2.reset() p.use_count()=0 p2.use_count()=0 p3.use_count()=1
A ball disappears.
after p3.reset() p.use_count()=0 p2.use_count()=0 p3.use_count()=0

转载请注明来源, from goldandrabbit.github.io

💰

×

Help us with donation