C++11:智能指针

C++11新增了 auto_ptr  unique_ptr  shared_ptr  weak_ptr 四种指针,第一个auto_ptr已经被弃用

unique_ptr 独占所指向的对象

智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象,当栈对象的生命周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏

 

一.auto_ptr

//p2指针取代了p1,访问p1指针会报错,auto_ptr 存在潜在的内存崩溃,已弃用

auto_ptr<string> p1;

auto_ptr<string> p2;

p2 = p1;

 

二.unique_ptr

unique_ptr实现独占式拥有和严格拥有概念,保证同一时间内只有一个智能指针指向该对象,避免资源泄漏

unique_ptr<string> p3;

unique_ptr<string> p4;

p4 = p3;  //会报错

 

三.shared_ptr

shared_ptr实现共享式指针,多个智能指针可以指向相同对象,该对象会在最后一个引用被销毁后释放

通过成员函数use_count()来查看资源的所有者个数,调用release()释放资源所有权

 

shared_ptr 允许多个指针指向同一个对象,weak_ptr 类指向 shared_ptr 所管理的对象 

shared_ptr是一种智能指针,作用如同指针,但会用引用计数记录不同的shared_ptr指向同一个对象,一旦对象的引用计数变为0,对象就会自动删除

 

都定义在 memory 头文件中

 

class Counter

{

public:

  Counter() : s(0), w(0){};

  int s;   //shared_ptr的引用计数

  int w;  //weak_ptr的引用计数

};

 

template <class T>

class WeakPtr;  //为了用weak_ptr的lock(),来生成shared_ptr用,需要拷贝构造用

 

template <class T>

class SharedPtr

{

public:

  SharedPtr(T* p = 0) : _ptr(p)

  {

    cnt = new Counter();

    if (p)

      cnt->s = 1;

    cout << "in construct" << cnt->s << endl;

  }

  ~SharedPtr()

  {

    release();

  }

  SharedPtr(SharedPtr<T> const& s)

  {

    cout << "in copy con" << endl;

    _ptr = s._ptr;

    (s.cnt)->s++;

    cout << "copy construct" << (s.cnt)->s << endl;

    cnt = s.cnt;

  }

  SharedPtr(WeakPtr<T> const& w)

  {

    cout << "in w copy con" << end;

    _ptr = w._ptr;

    (w.cnt)->s++;

    cout << "copy w construct" << (w.cnt)->s << endl;

    cnt = w.cnt;

  }  

  SharedPtr<T> &operator=(SharedPtr<T> &s)

  {

    if (this != &s)

    {

      release();

      (s.cnt)->s++;

      cout << "assign construct" << (s.cnt)->s << endl;

      cnt = s.cnt;

      _ptr = s._ptr;

    }

    return *this;

  }

  T &operator* ()

  {

    return *_ptr;

  }

  T *operator->()

  {

    return _ptr;

  }

  friend class WeakPtr<T>;  //方便weak_ptr与shared_ptr设置引用计数和赋值

 

protected:

  void release()

  {

    cnt->s--;

    cout << "release " << cnt->s << endl;

    if (cnt->s < 1)

    {

      delete _ptr;

      if (cnt->w < 1)

      {

        delete cnt;

        cnt = NULL;

      }

    }

  }

 

private:

  T* _ptr;

  Counter* cnt;

};

 

 

int main()

{

  string* s1 = new string("s1");

  

  shared_ptr<string> ps1(s1);

  shared_ptr<string> ps2;

  ps2 = ps1;

 

  cout << ps1.use_count() << endl;  // 2

  cout << ps2.use_count() << endl;  // 2

  cout << ps1.unique() << endl;     // 0

 

  string* s3 = new string("s3");

  shared_ptr<string> ps3(s3);

 

  cout << (ps1.get()) << endl;  //033AEB48

  cout << ps3.get() << endl;    //033B2C50

  swap(ps1, ps3);         //交换所拥有的对象

     cout << (ps1.get()) << endl;   //033B2C50

  cout << ps3.get() << endl;   //033AEB48

 

  cout << ps1.use_cout() << endl;  // 1

  cout << ps2.use_cout() << end;  // 2

  ps2 = ps1;

  cout << ps1.use_cout() << endl;  // 2

  cout << ps2.use_cout() << endl;  // 2

  ps1.reset();  //放弃ps1的拥有权,引用计数减少

  cout << ps1.use_cout() << endl;  // 0

  cout << ps2.use_cout() << endl;  // 1

}

 

shared_ptr<T> p         //空智能指针,可以指向类型为T的对象
unique_ptr<T> p 
p                       //将p用作一个条件判断,若p指向一个对象,则为true
*p                      //解引用p获得它指向的对象
p->get()                //返回p中保存的指针
swap(p, q)              //交换p q中的指针
p.swap(q)

Shared_ptr<T> p(q)
Shared_ptr<T> p(q, d)
Shared_ptr<T> p(p2, d)
p.reset()
p.reset(q)
p.reset(q, d)

 

#include <memory>
#include <iostream>

class Test
{
public:
  Test()
  {
    std::cout << "Test()" << std::endl;
  }
  ~Test()
  {
    std::cout << "~Test()" << std::endl;
  }
};

int main()
{
  std::shared_ptr<Test> p1 = std::make_shared<Test>();
  std::cout << "1 ref:" << p1.use_count() << std::endl;
  {
    std::shared_ptr<Test> p2 = p1;
    std::cout << "2 ref:" << p1.use_count() << std::endl;
  }
  std::cout << "3 ref:" << p1.use_count() << std::endl;
  return 0;
}

 

 

1.初始化

#include <iostream>

using namespace std;

int main()
{
  //默认初始化的智能指针保存着一个空指针
  shared_ptr<string> p1;
  if(!p1)
    cout<<"p1==NULL"<<endl;

  //初始化
  shared_ptr<string> p2(new string);
  if(p2 && p2->empty()){
    *p2 = "helloword"
    cout<< *p2 <<endl;
  }

  //一般的初始化方式
  shared_ptr<string> print(new string("normal usage!"));
  cout<<*print<<endl;

  //推荐安全的初始化方式
  shared_ptr<string> print1 = make_shared<string>("safe uage!")
  cout<< *pint1 <<endl;

}

 

// 错误初始化方式
shared_ptr<int> pa = new int(1);

int* p = new int(32);
shared_ptr<int> pp(p);
cout<< *pp << endl;

delete p;
cout<< *pp <<endl;

 

2.get()

get()返回一个内置指针,指向智能指针的管理对象

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

void useShared_ptr(int* p)
{
  cout<< *p <<endl;
}

void delePointer(int* p)
{
  delete p;
}

int main(int argc, char* argv[])
{
  shared_ptr<int> p1 = make_shared<int> (32);
  // shared_ptr<int> p2(p1.get())  错误,他们各自有内存的引用计数,不能拷贝过去

  useShared_ptr(p1.get());
  // delePointer(p1.get())  错误

  return 0;

}

 

3.make_shared<>()

安全分配和使用动态内存的方法是调用 make_shared() 标准库函数,此函数在动态内存中分配一个对象并初始化它,返回此对象的shared_ptr

 

#include <iostream>
using namespace std;

int main()
{
  shared_ptr<int> p3 = make_shared<int>(42);
  cout<< *p3 <<endl;

  shared_ptr<string> pstr = make_shared<string>("99999");
  cout<< *pstr <<endl;

  shared_ptr<int> pint = make_shared<int>();
  cout<< *pint <<endl;

  auto pau = make_shared<string>("auto");
  cout<< *pau <<endl;
 
}

 

4.shared_ptr的拷贝和赋值

 

5.引用计数

 

四.weak_ptr

shared_ptr智能指针有可能导致内存泄漏的风险,当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏

weak_ptr是用来解决shared_ptr相互引用造成死锁问题,是一种不控制对象生命周期的智能指针

weak_ptr设计的目的是为了配合shared_ptr而引入的一种智能指针来协助工作,它是对象的一种弱引用

weak_ptr一般通过shared_ptr来构造,通过expired函数检查原始指针是否为空,lock来转化为shared_ptr

 

template <class T>

class WeakPtr

{

public:  //给出默认构造和拷贝构造,其中拷贝构造不能有从原始指针进行构造

  WeakPtr()

  {

    _ptr = 0;

    cnt = 0;

  }

  WeakPtr(SharedPtr<T>& s) : _ptr(s._ptr), cnt(s.cnt)

  {

    cout << "w con s" << endl;

    cnt->w++;

  }

  WeakPtr(WeakPtr<T>& w) : _ptr(w._ptr), cnt(w.cnt)

  {

    cnt->w++;

  }

  ~WeakPtr()

  {

    release();

  }

  WeakPtr<T> &operator=(WeakPtr<T> &w)

  {

    if (this != &w)

    {

      release();

      cnt = w.cnt;

      cnt->w++;

      _ptr = w._ptr;

    }

    return *this;

  }

  WeakPtr<T> &operator=(SharedPtr<T> &s)

  {

    cout << "w = s" << endl;  

    release();

    cnt = s.cnt;

    cnt->w++;

    _ptr = s._ptr;

    return *this;

  }

  SharedPtr<T> lock()

  {

    return SharedPtr<T>(*this);

  }

  bool expired()

  {

    if (cnt)

    {  

      if (cnt->s > 0)

      {

        cout << "empty" << cnt->s << endl;

        return false;

      }

    }

    return true;

  }

  friend class SharedPtr<T>;  //方便weak_ptr与shared_ptr设置引用计数和赋值

 

protected:

  void release()

  {

    if (cnt)

    {

      cnt->w--;

      cout << "weakptr release" << cnt->w << endl;

      if (cnt->w < 1 && cnt->s < 1)

      {

        //delete cnt;

        cnt = NULL;

      }

    }

  }

 

private:

  T* _ptr;

  Counter* cnt;

};

 

 

posted @ 2019-09-06 14:45  言午丶  阅读(248)  评论(0编辑  收藏  举报