您的位置:首页 > 编程语言 > C语言/C++

用c++简单实现智能指针(转)

2014-09-01 11:25 246 查看
/article/2673481.html

用c++简单实现智能指针

什么是智能指针?答案相当简单;智能指针是聪明的普通指针。这是什么意思?实际上,智能指针是一些对象,表现出普通指针的功能但是比普通指针多做了一些事情。这些对象像普通指针一样灵活,并且管理对象有自己的优点(比如构造器和自动析构)。智能指针解决了普通指针的一些问题。

普通指针的问题。

我们使用C++语言中的指针,最常见的问题是什么?内存管理吧,请看下面的代码:

[cpp] view plaincopy

char* pName = new char[1024];



SetName(pName);





if(null != pName)

{

delete[] pName;

}

好多次我们都会忘记释放pNme,并且管理释放这些不会再用到的指针将会是很大的工程。可不可以指针自身进行管理?当然,智能指针就可以做到。我们实现一个智能指针,看看智能指针如何处理的更好。
下面写一个实际例子,先写一个叫做Person的类。

[cpp] view plaincopy

class Person

{

int age;

char* pName;

public:

Person(): pName(0),age(0)

{

}

Person(char* pName, int age): pName(pName), age(age)

{

}

~Person()

{

}

void Display()

{

printf("Name = %s Age = %d \n", pName, age);

}

void Shout()

{

printf("Ooooooooooooooooo");

}

};

下面是客户端代码使用Person类。

[cpp] view plaincopy

void main()

{

Person* pPerson = new Person("Scott", 25);

pPerson->Display();

delete pPerson;

}

现在我们来看这段代码,每当我创建一个指针,都要管理释放它。我要自动的释放它,智能指针可以。因此我们创建一个SP类来管理Person的对象,客户端的代码可以这样写:

[cpp] view plaincopy

void main()

{

SP p(new Person("Scott", 25));

p->Display();

// Dont need to delete Person pointer..

}

[cpp] view plaincopy

void main()

{

SP p(new Person("Scott", 25));

p->Display();

// Dont need to delete Person pointer..

}

注意:
1,我们创建了一个SP对象来管理Person的指针,当SP对象的作用域结束,会自动析构,它将释放Person的指针。
2,我们可以使用SP的对象p调用Display()函数,就像Person类的对象指针调用Display()函数,它的行为表现的像Person类的对象指针。
智能指针接口
智能指针表现出指针的行为,所以应该支持如下运算符:

Dereferencing (operator
*
)

Indirection (operator
->
)

下面实现智能指针SP:

[cpp] view plaincopy

class SP

{

private:

Person* pData; // pointer to person class

public:

SP(Person* pValue) : pData(pValue)

{

}

~SP()

{

// pointer no longer requried

delete pData;

}

Person& operator* ()

{

return *pData;

}

Person* operator-> ()

{

return pData;

}

};

这就是我们智能指针,当它的析构函数被调用时会释放Person类的对象指针。它也支持类似于指针的操作。

通用的智能指针

但是有个问题,我们智能控制Person类,也就是说每一种类型我们都要实现一个智能指针。我们可以使用模版使它通用。

[cpp] view plaincopy

template < typename T > class SP

{

private:

T* pData; // Generic pointer to be stored

public:

SP(T* pValue) : pData(pValue)

{

}

~SP()

{

delete pData;

}

T& operator* ()

{

return *pData;

}

T* operator-> ()

{

return pData;

}

};

void main()

{

SP<Person> p(new Person("Scott", 25));

p->Display();

// Dont need to delete Person pointer..

}

我们的智能指针这样就真的智能了吗?验证下面的代码:

[cpp] view plaincopy

void main()

{

SP<Person> p(new Person("Scott", 25));

p->Display();

{

SP<Person> q = p;

q->Display();

// Destructor of Q will be called here..

}

p->Display();

}

这样就会存在一个问题:p和q关联到了Person类的相同对象指针,当q结束它的作用域时会释放Person类的对象指针,我们用p调用Display()函数会因为垂悬指针而失败。我们应该在不使用它的时候再释放,智能指针中引入计数便可解决。

计数器。
下面实现一个计数器的类RC.

[cpp] view plaincopy

class RC

{

private:

int count; // Reference count

public:

void AddRef()

{

// Increment the reference count

count++;

}

int Release()

{

// Decrement the reference count and

// return the reference count.

return --count;

}

};

下面把计数器引入到我们的智能指针中:

[cpp] view plaincopy

template < typename T > class SP

{

private:

T* pData; // pointer

RC* reference; // Reference count

public:

SP() : pData(0), reference(0)

{

// Create a new reference

reference = new RC();

// Increment the reference count

reference->AddRef();

}

SP(T* pValue) : pData(pValue), reference(0)

{

// Create a new reference

reference = new RC();

// Increment the reference count

reference->AddRef();

}

SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)

{

// Copy constructor

// Copy the data and reference pointer

// and increment the reference count

reference->AddRef();

}

~SP()

{

// Destructor

// Decrement the reference count

// if reference become zero delete the data

if(reference->Release() == 0)

{

delete pData;

delete reference;

}

}

T& operator* ()

{

return *pData;

}

T* operator-> ()

{

return pData;

}

SP<T>& operator = (const SP<T>& sp)

{

// Assignment operator

if (this != &sp) // Avoid self assignment

{

// Decrement the old reference count

// if reference become zero delete the old data

if(reference->Release() == 0)

{

delete pData;

delete reference;

}

// Copy the data and reference pointer

// and increment the reference count

pData = sp.pData;

reference = sp.reference;

reference->AddRef();

}

return *this;

}

};

在看看客户端的代码:

[cpp] view plaincopy

Collapse | Copy Code

void main()

{

SP<PERSON> p(new Person("Scott", 25));

p->Display();

{

SP<PERSON> q = p;

q->Display();

// Destructor of q will be called here..

SP<PERSON> r;

r = p;

r->Display();

// Destructor of r will be called here..

}

p->Display();

// Destructor of p will be called here

// and person pointer will be deleted

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: