首页 > 试题广场 >

请简述智能指针原理,并实现一个简单的智能指针。

[问答题]
请简述智能指针原理,并实现一个简单的智能指针。
智能指针:实际指行为类似于指针的类对象 ,它的一种通用实现方法是采用引用计数的方法。
1.智能指针将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针。
2.每次创建类的新对象时,初始化指针并将引用计数置为1;
3.当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;
4.对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;这是因为左侧的指针指向了右侧指针所指向的对象,因此右指针所指向的对象的引用计数+1;
5.调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
6.实现智能指针有两种经典策略:一是引入辅助类,二是使用句柄类。这里主要讲一下引入辅助类的方法


//基础对象类,要做一个对Point类的智能指针
class Point
{
public:
    Point(int xVal = 0, int yVal = 0):x(xVal),y(yVal) { }
    int getX() const { return x; }
    int getY() const { return y; }
    void setX(int xVal) { x = xVal; }
    void setY(int yVal) { y = yVal; }
private:
    int x,y;
};

//辅助类,该类成员访问权限全部为private,因为不想让用户直接使用该类
class RefPtr   
{
    friend class SmartPtr;//定义智能指针类为友元,因为智能指针类需要直接操纵辅助类
    RefPtr(Point *ptr):p(ptr), count(1) { }
    ~RefPtr() { delete p; }

    int count; //引用计数
    Point *p;  //基础对象指针
};

//智能指针类
class SmartPtr                                             
{
public:
    SmartPtr(Point *ptr):rp(new RefPtr(ptr)) { }            //构造函数
    SmartPtr(const SmartPtr &sp):rp(sp.rp) { ++rp->count; } //复制构造函数
    SmartPtr& operator=(const SmartPtr& rhs) {              //重载赋值操作符
        ++rhs.rp->count;                                    //首先将右操作数引用计数加1,
        if(--rp->count == 0)                                                                     //然后将引用计数减1,可以应对自赋值
            delete rp;
        rp = rhs.rp;
        return *this;
    }
    ~SmartPtr() {                                           //析构函数
        if(--rp->count == 0)                                //当引用计数减为0时,删除辅助类对象指针,从而删除基础对象
            delete rp;
    }

private:
    RefPtr *rp;                                             //辅助类对象指针
};
发表于 2015-06-16 18:24:07 回复(5)
template<typename SmartPointer,typename Type>
class PtrCount{
	friend SmartPointer;
	PtrCount(Type* _p) :p(_p), use(1){}
	~PtrCount(){ delete p; }
	Type *p;
	size_t use;
};

template<typename Type>
class SmartPtr{
public:
	SmartPtr(Type* p) :ptrCnt(new PtrCount<SmartPtr, Type>(p)){};
	SmartPtr(const SmartPtr& orig):ptrCnt(orig.ptrCnt){
		++ptrCnt->use;
	}
	SmartPtr& operator=(const SmartPtr& rhs){
		++rhs.ptrCnt->use;
		if (--ptrCnt->use == 0)
			delete ptrCnt;
		ptrCnt = rhs.ptrCnt;
		return *this;
	}
	~SmartPtr(){
		if (--ptrCnt->use == 0)
			delete ptrCnt;
	}
private:
	PtrCount<SmartPtr, Type> *ptrCnt;
};

发表于 2015-07-21 10:42:39 回复(0)
智能指针是一种资源管理类,通过对原始指针进行封装,在资源管理对象进行析构时对指针指向的内存进行释放;通常使用引用计数方式进行管理,一个基本实现如下:
class Object;
class SmartPointer;

class Counter
{
 friend class SmartPointer;
public:
 Counter()
 {
  ptr = NULL;
  cnt = 0;
 }
 Counter(Object* p)
 {
  ptr = p;
  cnt = 1;
 }
 ~Counter()
 {
  delete ptr;
 }
private:
 Object* ptr;
 int cnt;
};

class SmartPointer
{
public:
 SmartPointer(Object* p)
 {
  ptr_counter = new Counter(p);
 }
 SmartPointer(const SmartPointer &sp)
 {
  ptr_counter = sp.ptr_counter;
  ++ptr_count->cnt;
 }
 SmartPointer& operator=(const SmartPointer &sp)
 {
  ++sp.ptr_counter->cnt;
  --ptr_counter->cnt;
  if (ptr_counter->cnt == 0)
  {
   delete ptr_counter;
  }
  ptr_counter = sp.ptr_counter;
 }
 ~SmartPointer()
 {
  - -ptr_counter->cnt;
  if (ptr_counter->cnt == 0)
  {
   delete ptr_counter;
  }
 }
private:
 Counter* ptr_counter;

}; 

发表于 2015-05-05 14:19:13 回复(0)
template<class T>
class SmartPtr
{
  private:
     T *ptr;
     int  *counter;
 public:
    SmartPtr(T *p):ptr(p),counter(new int(0))
   {
       if(p)
         *counter = 1;
   }
   SmartPtr(const SmartPtr& rhs)
   {
       ++*rhs.counter;
       ptr = rhs.ptr;
       counter = rhs.couter;
    }
    SmartPtr& operator=(const SmartPtr& rhs)   
    {
        --*counter;
       if(*counter == 0)
          delete ptr;
      ++*rhs.counter;
      ptr = rhs.ptr;
      counter = rhs.couter;
    }
    T* operator ->()
   {
       returnptr;
   }
   ~SmartPtr()
   {
       --*counter;
       if(*counter==0)
       {
           delete ptr;
           delete counter;
           ptr=NULL;
           count=NULL;
       }
   }
}
发表于 2015-05-24 11:37:31 回复(1)
/**
 *  智能指针,简单来讲是使用引用计数的方法,来跟踪监控指针。当引用计数为0时就delete 所跟踪的目标指针,释放内存
 *  智能指针将一个指针封装到一个类中,当调用智能指针的拷贝构造函数时,将引用计数+1(因为新创建的智能指针也引用了目标指针)
 *  重载智能指针的赋值操作符,等号左边的对象引用计数-1,右边的对象引用计数+1,右边的目标指针和引用计数赋值给左边的对象
 *  智能指针的析构函数将引用计数-1,并判断是否为0,如果是的话delete 目标指针。
 */
template <class T>
class smart_ptr
{
private:
    T* ptr;
    int* count;
public:
    smart_ptr(T* p=0):ptr(p),count(new int(0))
    {
        if(p)
            *count=1;
    }
    smart_ptr(const smart_ptr& src)
    {
        ++*src.count;
        count=src.count;
        ptr=src.ptr;
    }
    smart_ptr& operator =(const smart_ptr& src)
    {
        --*count;
        if(*count==0)
            delete ptr;
        count=src.count;
        ++*count;
        ptr=src.ptr;
    }
    const smart_ptr& operator =(const smart_ptr& src) const
    {
        --*count;
        if(*count==0)
            delete ptr;
        count=src.count;
        ++*count;
        ptr=src.ptr;
    }
    T* operator ->()
    {
        return ptr;
    }
    ~smart_ptr()
    {
        --*count;
        if(*count==0)
        {
            delete ptr;
            delete count;
            ptr=NULL;
            count=NULL;
        }
    }
};

编辑于 2015-05-28 08:25:50 回复(3)

我是面试官的话这些没有一个能满意的,首先一定是模板类就不说了。智能指针就有auto_prr unique_ptr scoped_ptr shared_ptr 当然还有辅助的weak_ptr,首先明确要哪一种,毕竟不要说哪一种就一定多么牛逼,有的是历史老一点,但有时候没有C++11支持可能只能用auto_ptr,有时候我们只需要用一个指针管理对象也就没必要去shared_ptr,所以每个都要很熟悉怎么写,各自都是什么模型。每种怎么写都有很好的参考,希望所有看到这个的人都一定要都好好掌握。

发表于 2018-11-25 23:49:04 回复(0)
1 智能指针的简单介绍及代码;2 c++智能指针的区别;3 智能指针存在的问题及解决办法
1 智能指针是一个资源管理类,对于其他类的指针进行管理,在析构函数中将指针进行释放。
#include <iostream>
using namespace std;
// 具体操作类
class Object
{
public:
    int a;
    int b;
};
// 操作函数
void Process(Object* p)
{
    // do something
};
class Counter
{
    friend class SmartPointer;
public:
    Counter()
    {
        ptr=NULL;
        cnt=0;
    }
    Counter(Object* p)
    {
        ptr=p;
        cnt=1;
    }
    ~Counter()
    {
        delete ptr;
    }
private:
    Object* ptr;
    int cnt;
}

class SmartPointer
{
public:
    SmartPointer(Object* p)
    {
        ptr_pointer=new Counter(p);
    }
    SmartPointer(const SmartPointer &sp)
    {
        ptr_counter=sp.ptr_counter;
        ++ptr_counter->cnt;
    }
    SmartPointer& operator=(const SmartPointer)
    {
        ++sp.ptr_counter->cnt;
        --ptr_counter.cnt;
        if(ptr_counter.cnt==0)
        {
            delete ptr_counter;
        }
        ptr_counter=sp.ptr_counter;
    }
    ~Smartpointer()
    {
        --ptr_counter->cnt;
        if(ptr_counter->cnt==0)
        {
            delete ptr_counter;
        }
    }
private:
    Counter* ptr_counter;
};

int main()
{
    SmartPointer p(new Object());
    Process(p);
}
2 C++智能指针主要有: unique_ptr;shared_ptr;weak_ptr三种
unique_ptr 可以移到新所有者,但不会复制或共享(无法得到指向)
3 循环引用
采用weak_ptr;

发表于 2021-03-14 14:14:02 回复(0)
Class Object;
Class SmartPointer;
Class Counter
{
friend class SmartPointer;
public:
        Counter(): ptr(NULL), cnt(0)
        {

        }

        Counter(Object *obj)
        {
            ptr = obj;
            cnt = 1;
        }

       ~Counter()
        {
            delete ptr;
        }
private:
    int cnt;
    Object *ptr;
};

Class SmartPointer
{
public:
        SmartPointer(Object *p)
        {
            ptr_counter = new Counter(p);
        }

      SmartPointer(SmartPointer &p)
      {
            ptr_counter = p->ptr_counter;
            ++ptr_counter->cnt;
       } 

      SmartPointer& operator = (SmartPointer &sp)
      {
            ++sp->ptr_counter->cnt;
            --ptr_counter->cnt;
            if (ptr_counter->cnt == 0)
            {
                delete ptr_counter;
            }

            ptr_counter = sp->ptr_counter;
            return *this;
      }     

       ~SmartPointer()
        {
            --ptr_counter->cnt;
            if (ptr_counter->cnt == 0)
            {
                delete ptr_counter;
            }
        }
private:
       Counter *ptr_counter;    
};


发表于 2015-07-26 20:08:39 回复(0)
智能指针是一个资源管理类,通过对原始指针进行封装,在资源管理对象进行析构时对指针指向的内存进行释放,通常使用引用计数方式进行管理。
class U_Ptr{
friend class HasPtr;
int *io;
size_t use;
U_Ptr(int *p):ip(p),usr(1){}
~U_Ptr() {delete ip;}
};

class HasPtr{
public:
HasPtr(int *p,int i):ptr(new U_Ptr(p)),val(i)){}
HasPtr(const HasPtr &orig):ptr(orig.ptr),cal(orig.val) {++ptr->use;}
HasPtr& operator=(const HasPtr& rhs){
++rhs.ptr->use;
if(----ptr->use == 0)
 delete ptr;
ptr=rhs.ptr;
val=rhs.val;
return *this;}

~HasPtr(){
if(--ptr->use == 0 )delete ptr;}

private:
U_Ptr *ptr;
int val;
};
发表于 2015-06-11 20:09:57 回复(0)
智能指针是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。
#include <iostream>  
#include <stdexcept>  
using namespace std;  
  
#define TEST_SMARTPTR  
class Stub  
{  
public:  
    void print() {  
        cout<<"Stub: print"<<endl;  
    }  
    ~Stub(){  
        cout<<"Stub: Destructor"<<endl;  
    }  
};  
  
template <typename T>  
class SmartPtr   
{  
public:  
    SmartPtr(T *p = 0): ptr(p), pUse(new size_t(1)) { }  
    SmartPtr(const SmartPtr& src): ptr(src.ptr), pUse(src.pUse) {  
        ++*pUse;  
    }  
    SmartPtr& operator= (const SmartPtr& rhs) {  
        // self-assigning is also right  
        ++*rhs.pUse;  
        decrUse();  
        ptr = rhs.ptr;  
        pUse = rhs.pUse;  
        return *this;  
    }  
    T *operator->() {  
        if (ptr)  
            return ptr;  
        throw std::runtime_error("access through NULL pointer");  
    }  
    const T *operator->() const {   
        if (ptr)  
            return ptr;  
        throw std::runtime_error("access through NULL pointer");  
    }  
    T &operator*() {  
        if (ptr)  
            return *ptr;  
        throw std::runtime_error("dereference of NULL pointer");  
    }  
    const T &operator*() const {  
        if (ptr)  
            return *ptr;  
        throw std::runtime_error("dereference of NULL pointer");  
    }   
    ~SmartPtr() {  
        decrUse();  
#ifdef TEST_SMARTPTR  
        std::cout<<"SmartPtr: Destructor"<<std::endl; // for testing  
#endif  
    }  
      
private:  
    void decrUse() {  
        if (--*pUse == 0) {  
            delete ptr;  
            delete pUse;  
        }  
    }  
    T *ptr;  
    size_t *pUse;  
};  
  
int main()  
{  
    try {  
        SmartPtr<Stub> t;  
        t->print();  
    } catch (const exception& err) {  
        cout<<err.what()<<endl;  
    }  
    SmartPtr<Stub> t1(new Stub);  
    SmartPtr<Stub> t2(t1);  
    SmartPtr<Stub> t3(new Stub);  
    t3 = t2;  
    t1->print();  
    (*t3).print();  
      
    return 0;  
}

发表于 2015-06-11 15:57:50 回复(0)
/*
*my shared_ptr:  share_ptr
*author:ERIC
*blog:http://www.ilovecpp.com
*time:2015-5-27 23:56:43
*/

template <typename T> class share_ptr {
private:
    T* __ptr;
    int* __pcounts;
public:
    share_ptr(T* p= NULL);
    share_ptr(const share_ptr<T>& src);
    share_ptr& operator=(share_ptr<T>& src);
    ~share_ptr();
    operator bool() const;//支持if(p)形式
    T* operator-> () const;
    T& operator*() const;
    T* get() const;
    int use_counts() const;//返回引用计数
    bool unique() const;//当前智能指针是否唯一
    void swap(share_ptr& rhs);//交换,成员函数
    template <typename Type>//友元函数,交换两个智能指针
    friend void swap(share_ptr<Type>& lhs,share_ptr<Type>& rhs);
};

template<typename T>
share_ptr<T>::share_ptr(T* p)
    :__ptr(p),__pcounts(new int(0))
{
    if(__ptr)
        *__pcounts = 1;
}

template<typename T>
share_ptr<T>::~share_ptr()
{
    --*__pcounts;
    if(*__pcounts == 0)
    {//空智能指针这里delete  __ptr也安全,delete NULL;
        delete __pcounts;
        delete __ptr;
    }
}

/*__ptr(new T(src)) 很重要 ,如果直接__ptr(new T)
*会由于T类没有默认构造函数而出错
*测试的时候才发现这个问题的
*/
template<typename T>
share_ptr<T>::share_ptr (const share_ptr<T>& src)
    :__pcounts(new int),__ptr(new T(src))
{
    ++*src.__pcounts;
    __ptr = src.__ptr;
    __pcounts = src.__pcounts;
}

template <typename T>
share_ptr<T>& share_ptr<T>::operator= (share_ptr<T>& src)
{
    --*__pcounts;
    //如果是空智能指针的话 __pcounts == -1,那块内存也得释放
    if(*__pcounts == 0 || *__pcounts == -1)
        delete __pcounts;
    ++*src.__pcounts;
    __ptr = src.__ptr;
    __pcounts = src.__pcounts;
    return *this;
}

//支持if(p)这样的操作
template<typename T>
share_ptr<T>::operator bool() const
{
    return __ptr;
}

template<typename T>
T* share_ptr<T>::operator->() const
{
    return __ptr;
}

template<typename T>
T& share_ptr<T>::operator*() const
{
    return *__ptr;
}


template<typename T>
T* share_ptr<T>::get() const
{
    return __ptr;
}

template<typename T>
int share_ptr<T>::use_counts() const
{
    return *__pcounts;
}

template<typename T>
bool share_ptr<T>::unique() const
{
    if(*__pcounts == 1)
        return true;
    else
        return false;
}

template<typename T>
void share_ptr<T>::swap(share_ptr<T>& rhs)
{
    T* tmpPtr = rhs.__ptr;
    rhs.__ptr = __ptr;
    __ptr = tmpPtr;
    int* tmpPcounts = rhs.__pcounts;
    rhs.__pcounts = __pcounts;
    __pcounts = tmpPcounts; 
}

template<typename T>
void swap(share_ptr<T>& lhs,share_ptr<T>& rhs)
{
    T* tmpPtr = rhs.__ptr;
    rhs.__ptr = lhs.__ptr;
    lhs.__ptr = tmpPtr;
    int* tmpPcounts = rhs.__pcounts;
    rhs.__pcounts = lhs.__pcounts;
    lhs.__pcounts = tmpPcounts; 
}

//c++11 make_shared<T>(args) 
template<typename T>
share_ptr<T> make_share(T args)
{
    return new T(args);
}

发表于 2015-05-28 21:32:42 回复(0)