C++智能指针

来源:互联网 发布:淘宝买家贷款操作流程 编辑:程序博客网 时间:2024/06/07 07:20

内存泄露一直是C++程序员头疼的问题。下面就简单理解下C++智能指针。

 

智能指针 是存储指向动态分配对象指针的类。 目的是能够自动正确的销毁内存,防止内存泄露。

用的实现技术是使用引用计数(reference count),将一个计数器与类指向的对象相关联。引用计数跟踪该类有多少个对象共享同一指针

创建一个类的对象时, 初始化指针并且将引用计数置为1;

当一个对象作为另一个对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相关的引用计数。

对一个对象进行赋值时,赋值操作符减少左操作数的引用计数,如引用计数为0, 删除对象, 释放对象指向的内存

并增加右操作符所指对象的引用计数。

调用析构函数时,减少引用计数, 如果引用计数为0, 删除对象, 释放对象指向的内存

 

设计思路:

由于需要一个引用计数和一个指针动态内存,将他们封装为一个类

 定义一个Uptr类,成员函数为引用计数和指针。 实现构造函数, 析构函数, 拷贝构造函数和赋值运算符重载。

设计一个管理类HasPtr, 管理这个Uptr类的引用计数和指针,将HasPtr声明为Uptr类的友元类。即只有HasPtr可以访问为Uptr类。

用2个类实现的好处是 解耦合,增加智能指针的可扩展性,引用计数和指针是不变的, 智能指针的管理是可变的, 将可变的和不变的逻辑分离出来。

class Uptr{/*Uptr has private member, only HasPtr class can access it*/friend class HasPtr;private:Uptr(int *p):m_ptr(p),m_useNum(1) {cout<< "Uptr constructor called" << endl;}~Uptr() {if(NULL!=m_ptr) {delete []m_ptr; m_ptr = NULL;}cout << "Uptr destructor called" << endl;}Uptr(const Uptr& o){m_ptr = o.ptr;}Uptr& operator=(const Uptr& o){if (&o == this){return;}if (m_ptr != NULL){delete []m_ptr;}//shallow copym_ptr = o.m_ptr;}private:int* m_ptr;int m_useNum;};


下面是实现HasPtr 管理类

class HasPtr{public:HasPtr(int *p):m_ptr(new Uptr(p)) {cout << "HasPtr constructor called!" << "use=" <<m_ptr->m_useNum << endl;}HasPtr(const HasPtr& o){m_ptr = o.m_ptr;/*add the useNum when copy*/++m_ptr->m_useNum;cout << "HasPtr copy constructor called!" << "use=" <<m_ptr->m_useNum << endl;}HasPtr& operator=(const HasPtr& o);~HasPtr(){/*delete the useNum when destructor*/if (--m_ptr->m_useNum == 0){delete m_ptr;}cout << "HasPtr distructor called!" << "use=" <<m_ptr->m_useNum << endl;}void set_ptr(int *p){if (p == NULL){delete m_ptr;}m_ptr->m_ptr = p;}int* get_ptr() const{return m_ptr->m_ptr;}private:Uptr* m_ptr;};HasPtr& HasPtr::operator=(const HasPtr& o){cout << "operator= called" << endl;if (&o == this){return *this;}++o.m_ptr->m_useNum;/*release the memory if it is neccessary*/if (--m_ptr->m_useNum == 0){delete m_ptr;}m_ptr = o.m_ptr;return *this;}

其中有几个需要注意的地方:

赋值运算符重载要考虑 自己赋值给自己的特殊情况, 一个智能指针类对象给另一个智能指针类对象赋值时, 赋值操作符减少左操作数的引用计数,如引用计数为0, 删除对象, 释放对象指向的内存并增加右操作符所指对象的引用计数。

 


 

 

 

全部程序:

/**describe: realize smart point, keep improve*/#include <iostream>#include <string.h>using namespace std;/*use two class realize the function. high cohesion and low coupling*/class Uptr{/*Uptr has private member, only HasPtr class can access it*/friend class HasPtr;private:Uptr(int *p):m_ptr(p),m_useNum(1) {cout<< "Uptr constructor called" << endl;}~Uptr() {if(NULL!=m_ptr) {delete []m_ptr; m_ptr = NULL;}cout << "Uptr destructor called" << endl;}Uptr(const Uptr& o){m_ptr = o.ptr;}Uptr& operator=(const Uptr& o){if (&o == this){return;}if (m_ptr != NULL){delete []m_ptr;}//shallow copym_ptr = o.m_ptr;}private:int* m_ptr;int m_useNum;};class HasPtr{public:HasPtr(int *p):m_ptr(new Uptr(p)) {cout << "HasPtr constructor called!" << "use=" <<m_ptr->m_useNum << endl;}HasPtr(const HasPtr& o){m_ptr = o.m_ptr;/*add the useNum when copy*/++m_ptr->m_useNum;cout << "HasPtr copy constructor called!" << "use=" <<m_ptr->m_useNum << endl;}HasPtr& operator=(const HasPtr& o);~HasPtr(){/*delete the useNum when destructor*/if (--m_ptr->m_useNum == 0){delete m_ptr;}cout << "HasPtr distructor called!" << "use=" <<m_ptr->m_useNum << endl;}void set_ptr(int *p){if (p == NULL){delete m_ptr;}m_ptr->m_ptr = p;}int* get_ptr() const{return m_ptr->m_ptr;}private:Uptr* m_ptr;};HasPtr& HasPtr::operator=(const HasPtr& o){cout << "operator= called" << endl;if (&o == this){return *this;}++o.m_ptr->m_useNum;/*release the memory if it is neccessary*/if (--m_ptr->m_useNum == 0){delete m_ptr;}m_ptr = o.m_ptr;return *this;}/*for test*/void test_func(){int* pValue = new int(10);int* pValue1 = new int(20);if (NULL == pValue){return;}HasPtr ptr1(pValue);HasPtr ptr2(ptr1);HasPtr ptr3 = ptr1;HasPtr ptr4(pValue1);ptr4 = ptr1;cout << endl;}int main(int argc, char** argv){test_func();return 0;}

运行结果


 

原创粉丝点击