C++中的智能指针

简单来说,C++智能指针是包含重载运算符的类,其行为像是常规的指针,但智能指针能够及时,妥善地销毁动态分配的数据,并实现了明确的对象生命周期。智能指针的关键在于,重载 引用运算符(*)和成员选择运算符(->).使智能指针真正智能的是复制构造函数、赋值运算符和析构函数的实现。它们决定了智能指针对象被传递给函数、赋值或者离开作用域时的行为。

智能指针最基本的组成部分:

template <typename T>
class smart_pointer
{
private:
    T* rawPtr;
public:
    smart_pointer (T* pData) : rawPtr (pData) {}    // constructor
    ~smart_pointer () {delete rawPtr;};                    // destructor

    // copy constructor
    smart_pointer (const smart_pointer & anotherSP);
    // copy assignment operator
    smart_pointer& operator= (const smart_pointer& anotherSP);    

    T& operator* () const        // dereferencing operator
    {
        return *(rawPtr);
    }

    T* operator-> () const        // member selection operator
    {
        return rawPtr;
    }
};

// empty stub to enable compilation
int main()
{
	return 0;
}

智能指针的类型

  • 深复制
  • 写时拷贝
  • 引用计数
  • 引用链接
  • 破坏性复制

使用深复制的智能指针:

template <typename T>
class deepcopy_smart_ptr
{
private:
    T* object;
public:
    //... other functions

    // copy constructor of the deepcopy pointer
    deepcopy_smart_ptr (const deepcopy_smart_ptr& source)
    {
        // Clone() is virtual: ensures deep copy of Derived class object
        object = source->Clone ();
    }

   // copy assignment operator
   deepcopy_smart_ptr& operator= (const deepcopy_smart_ptr& source)
   {
      if (object)
         delete object;

        object = source->Clone ();
   }
};
   
// stub to ensure compilation
int main()
{
   return 0;
}

我的理解,在多态中简单的值传递可能会导致切除问题,只是保留基类的部分。如果使用的是深复制的智能指针的话,就可以避免此类问题。

改进的情况,写时复制(COW),只有在有人要修改内容的时候,才拷贝出来一份副本出来。而其他指针实例任然共享源对象。

引用计数智能指针

这种智能指针在复制的时候,需要将对象的引用计数加1,一般有两种方法:在对象中维护引用计数;引用计数由共享对象中的指针类维护。注意:在使用智能指针管理对象的同时,让原始指针指向它是一种糟糕的做法。当引用计数减为零的时候而释放对象,原始指针将指向不属于当前应用程序的内存。如果两个引用对象分别存储指向对方的指针,那么这两个对象永远不会被释放。

引用链接智能指针

不主动维护对象的引用计数,而只需要知道计数什么时候变为0,以便释放对象。其实现是基于双向链表的。

破坏性复制

破坏性指针的机制,在智能指针被复制时,将对象的所有权交给目标指针并重置原来的指针。它的一个优点:可以保证任何时刻只有一个活动的指针指向对象。该智能指针的复制构造函数和赋值运算符不能接受const引用,因为它在复制源引用后使其无效了。鉴于这种智能指针销毁源引用,所以不适用于STL容器。

一个破坏性复制智能指针:

template <typename T>
class destructivecopy_ptr
{
private:
   T* object;
public:
   destructivecopy_ptr(T* input):object(input) {}
   ~destructivecopy_ptr() { delete object; }

   // copy constructor
   destructivecopy_ptr(destructivecopy_ptr& source)
   {
      // Take ownership on copy
      object = source.object;

      // destroy source
      source.object = 0;
   }

   // copy assignment operator
   destructivecopy_ptr& operator= (destructivecopy_ptr& source)
   {
      if (object != source.object)
      {
         delete object;
         object = source.object;
         source.object = 0;
      }
   }
};

int main()
{
   destructivecopy_ptr<int> num (new int);
   destructivecopy_ptr<int> copy = num;

   // num is now invalid
   return 0;
}

使用std::unique_ptr

要使用std:unique_ptr, 必须包含头文件<memory>:

#include <memory>

这是一种简单的智能指针,但其复制构造函数和赋值运算符被声明为私有的,因此不能复制它,即不能将其按值传递给函数,也不能将其赋给其他指针。

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

class Fish
{
public:
    Fish() {cout << "Fish: Constructed!" << endl;}
    ~Fish() {cout << "Fish: Destructed!" << endl;}

    void Swim() const {cout << "Fish swims in water" << endl;}
};

void MakeFishSwim(const unique_ptr<Fish>& inFish)
{
   inFish->Swim();
}

int main()
{
   unique_ptr<Fish> smartFish (new Fish);

   smartFish->Swim();
   MakeFishSwim(smartFish); // OK, as MakeFishSwim accepts reference

   unique_ptr<Fish> copySmartFish;
   // copySmartFish = smartFish; // error: operator= is private

   unique_ptr<Fish> sameFish (std::move(smartFish)); 
   // smartFish is empty henceforth

   return 0;
}

编写使用多个线程的应用程序时,可以考虑std::shared_ptr和std::weak_ptr,它们可帮助您实现线程安全和引用计数对象的共享。

有兴趣的同学可以了解下Boost库(www.boost.org)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值