開(kāi)篇語(yǔ):這是在這里寫(xiě)的第一篇日志。關(guān)于來(lái)到這里,主要源于前兩天在這里看到一個(gè)牛人(vczh)的文章,花了近兩天斷斷續(xù)續(xù)拜讀了其文章。他的文章我不是全部能看懂,事實(shí)上只看懂了一小部分。還看到一些評(píng)論的朋友,也都很牛。因此想到這里來(lái)更好的與牛人們交流。如此而已。我原先的博客在 CSDN(http://blog.csdn.net/cnStreamlet/),由于一直以來(lái)都比較浮躁,也沒(méi)寫(xiě)什么有用的東西?,F(xiàn)在想想,人家是 05 級(jí),我也是 05 級(jí),人家已經(jīng)這么牛了,我卻還在金字塔的底層徘徊。人生短短幾個(gè)秋,年輕的時(shí)候是個(gè)學(xué)習(xí)的黃金時(shí)間,浪費(fèi)了豈不太可惜?總之呢,不管能不能靜下心來(lái),現(xiàn)在開(kāi)始努力靜下心來(lái),多學(xué)點(diǎn)技術(shù),即便成不了牛人,至少可以多些茶余飯后的談資。
==========華麗的分割線(xiàn)==========
好了,言歸正傳。今年 3 月份,也就是上班的第一個(gè)月,那時(shí)候我還算比較淡定的,經(jīng)常研究些玩意兒。那時(shí)寫(xiě)了個(gè)很輕量級(jí)的智能指針。現(xiàn)在不妨拿出來(lái)復(fù)習(xí)一下,如果有朋友路過(guò),歡迎指教。
我所理解的“智能指針”,就是達(dá)到 new 了之后不用 delete 的效果。利用棧變量在作用域結(jié)束后會(huì)自動(dòng)釋放(對(duì)象自動(dòng)析構(gòu))的機(jī)制,可以達(dá)到這個(gè)效果。設(shè)想有一個(gè)類(lèi),它以一個(gè)現(xiàn)有指針為參數(shù)進(jìn)行構(gòu)造,這個(gè)析夠的時(shí)候去 delete 這個(gè)指針,就可以了。然后問(wèn)題來(lái)了,在這種情形下,這個(gè)類(lèi)本身充當(dāng)了指針這個(gè)角色,那么難免要被復(fù)制來(lái)復(fù)制去,這個(gè)類(lèi)中的原始指針也要被復(fù)制,那么,顯然析構(gòu)函數(shù)里不能簡(jiǎn)單地 delete 了。這時(shí)候,比較流行的做法之一是使用引用計(jì)數(shù),當(dāng)某個(gè)對(duì)象被復(fù)制一次,計(jì)數(shù)加 1;被析構(gòu)一次,計(jì)數(shù)減 1。當(dāng)且僅當(dāng)計(jì)數(shù)為 0 的時(shí)候才執(zhí)行 delete?,F(xiàn)在,這個(gè)類(lèi)的雛形大概是:
template <typename T>
class QIPtr
{
public:
QIPtr(T *pData);
~QIPtr();
private:
T *m_pData;
size_t m_cRef; // TBD
private:
void AddRef();
void Release();
};
我現(xiàn)在很隨意地放了一個(gè) size_t m_cRef,但是細(xì)想一下這樣是不行的。假設(shè)有 QIPtr
p1(new int);,又有 QIPtr p2 = p1(當(dāng)然,拷貝構(gòu)造函數(shù)以及賦值函數(shù)現(xiàn)在還沒(méi)實(shí)現(xiàn),但這不妨礙我們想象他們的功能),p1 和 p2 里的 m_pData 共享一塊內(nèi)存,而 m_cRef 卻是獨(dú)立的,也就是說(shuō),p1 的 Release() 操作將無(wú)法影響到 p2。為了解決這個(gè)問(wèn)題,可以將引用計(jì)數(shù)也定為指針 size_t *m_pcRef,當(dāng)一個(gè)對(duì)象被使用原始指針構(gòu)造的時(shí)候,同時(shí)給 m_pcRef new 一個(gè)出來(lái);如果是 QIPtr 對(duì)象之間拷貝拷貝去,則將他們的 m_pcRef 也同步拷貝,并且讓 *m_pcRef 自增即可。
當(dāng)時(shí)我就做到這種程度(現(xiàn)在還是)。不過(guò)留有一個(gè)問(wèn)題,這個(gè)智能指針不是線(xiàn)程安全的,原因在于 AddRef() 和 Release() 期間沒(méi)有加鎖。
代碼比較短,就 200 行左右,如下:
/*******************************************************************************
Copyright (C) Streamlet. All rights reserved.
File Name: xlQIPtr.h
Author: Streamlet
Create Time: 2009-03-22
Description: Smart pointer
Version history:
2009-03-22 Created by Streamlet.
2009-03-27 Released first version.(1.0.0.1)
*******************************************************************************/
#ifndef __XLQIPTR_H_B0788703_ABD1_457D_8FEC_E527581FD9EF_INCLUDED__
#define __XLQIPTR_H_B0788703_ABD1_457D_8FEC_E527581FD9EF_INCLUDED__
namespace xl
{
#ifndef NULL
#define NULL 0
#endif
/// @brief Smart Pointer.
template <typename T>
class QIPtr
{
public:
/**
* @brief Default constructor.
*/
QIPtr();
/**
* @brief Constructor. Must give an heap address. Sample use: QIPtr<int> p(new int);.
* @param pData [in] A heap address, usually returned by operator new.
* @remark operator delete must not be called, if using QIPtr.
*/
QIPtr(T *pData);
/**
* @brief Copy construction.
* @param that [in] The pointer to be copied.
*/
QIPtr(const QIPtr<T> &that);
/**
* @brief Destroyer. Inside this function, the heap address will be released if there is no more references.
*/
~QIPtr();
public:
/**
* @brief Operator *, use it as usual.
* @return return a reference of T-typed object.
*/
T &operator*() const;
/**
* @brief Operator ->, use it as usual.
* @return return the address of the object.
*/
T *operator->() const;
/**
* @brief Copy operator, use it as usual.
* @param that [in] The pointer to be copied.
* @return Reference of this object
*/
QIPtr<T> &operator=(const QIPtr<T> &that);
/**
* @brief Compare operator, use it as usual.
* @param that [in] The pointer to be compared.
* @return Return true if the two points equals, return false otherwise.
*/
bool operator==(const QIPtr<T> &that) const;
/**
* @brief Compare operator, use it as usual.
* @param that [in] The pointer to be compared.
* @return Return true if the two points do not equals, return false otherwise.
*/
bool operator!=(const QIPtr<T> &that) const;
private:
void AddRef();
void Release();
private:
T *m_pData;
size_t *m_pcRefs;
};
template <typename T>
inline void QIPtr<T>::AddRef()
{
if (this->m_pcRefs == NULL)
{
this->m_pcRefs = new size_t;
*this->m_pcRefs = 0;
}
++*this->m_pcRefs;
}
template <typename T>
inline void QIPtr<T>::Release()
{
if (this->m_pcRefs == NULL)
{
return;
}
if (--*this->m_pcRefs > 0)
{
return;
}
delete this->m_pcRefs;
//if (this->m_pData == NULL)
//{
// return;
//}
delete this->m_pData;
}
template <typename T>
inline QIPtr<T>::QIPtr() : m_pData(NULL), m_pcRefs(NULL)
{
}
template <typename T>
inline QIPtr<T>::QIPtr(T *pData) : m_pData(NULL), m_pcRefs(NULL)
{
this->m_pData = pData;
this->AddRef();
}
template <typename T>
inline QIPtr<T>::QIPtr(const QIPtr<T> &that) : m_pData(NULL), m_pcRefs(NULL)
{
this->m_pData = that.m_pData;
this->m_pcRefs = that.m_pcRefs;
this->AddRef();
}
template <typename T>
inline QIPtr<T>::~QIPtr()
{
this->Release();
}
template <typename T>
inline T &QIPtr<T>::operator*() const
{
return *this->m_pData;
}
template <typename T>
inline T *QIPtr<T>::operator->() const
{
return this->m_pData;
}
template <typename T>
inline QIPtr<T> &QIPtr<T>::operator=(const QIPtr<T> &that)
{
//if (this == &that)
//{
// return *this;
//}
if (this->m_pData == that.m_pData)
{
return *this;
}
this->Release();
this->m_pData = that.m_pData;
this->m_pcRefs = that.m_pcRefs;
this->AddRef();
return *this;
}
template <typename T>
inline bool QIPtr<T>::operator==(const QIPtr<T> &that) const
{
return this->m_pData == that.m_pData;
}
template <typename T>
inline bool QIPtr<T>::operator!=(const QIPtr<T> &that) const
{
return this->m_pData != that.m_pData;
}
} // namespace xl
#endif // #ifndef __XLQIPTR_H_B0788703_ABD1_457D_8FEC_E527581FD9EF_INCLUDED__
寫(xiě)了這么粗淺的文字,希望大家不要笑話(huà)。請(qǐng)多指教。
posted on 2009-09-23 08:07
溪流 閱讀(572)
評(píng)論(4) 編輯 收藏 引用 所屬分類(lèi):
C++