| 项目搜索 |
| |
|
代码片段库:
查看代码片段
浏览
| 提交新的代码片段
| 创建代码包
智能指针类
|
类型:
Class |
类别:
Other
|
许可证:
GNU General Public License |
语言:
C++
|
描述:
使用 new 操作符为指定的类型 T(可以为类、结构体以及基本类型)
创建对象实例(数组),而且无需用户显示释放内存(另外:即使程
序非法退出,只要 C++ 对象被保证清除,那么就不会有任何内存泄漏)。
用户可以将 JCreateInst 变量作为 T * 指针使用。
|
该代码片段的版本系列:
片段ID |
下载版本 |
提交时间 |
提交人 |
删除 |
4582 | 1.1 | 2003-01-11 13:37 | jjyathefei | |
点击"下载版本"来下载该代码片段.
最新版本的代码片段: 1.1
/**********************************************************************************************
*模板类 JCreateInst
*功能:使用 new 操作符为指定的类型 T(可以为类、结构体以及基本类型)
* 创建对象实例(数组),而且无需用户显示释放内存(另外:即使程
* 序非法退出,只要 C++ 对象被保证清除,那么就不会有任何内存泄漏)。
* 用户可以将 JCreateInst 变量作为 T * 指针使用。
*注意:如果您编写多线程程序,请使能 #define JCREATEINST_MULTI_THREAD
* 如果您要在控制台上打印出内存使用情况,请使能 #define JCREATEINST_DEBUG 标志
* 如果您要使用 UNICODE 编码方式,请将 #define UNICODE 标志拷贝到程序入口点 WinMain() 或 main() 前
*不适用范围:对于 VCL 类库不使用,因为 VCL 类库有其自身掌握内存分配与释放
*
*Author: 蒋建宇
*Email: [email protected]
*******************
*Ver: 1.1
*Date: 2003.01.11
*******************
*Ver: 1.0
*Date: 2002.09.27
**********************************************************************************************/
#ifndef JCREATEINST_H
#define JCREATEINST_H
#define JCREATEINST_DEBUG //如果不需要在控制台上打印内存分配情况,则注释掉
#define JCREATEINST_MULTI_THREAD //如果不是多线程程序,则注释掉(这样可以改善程序性能;如果不注释掉,会降低单线程程序的执行效率)
//#define UNICODE // JCreateInst.h 支持 UNICODE 代码。如果想使用 UNICODE 编码,请将此行拷贝到程序入口点 WinMain() 或 main() 前
#ifdef UNICODE
#define _UNICODE
#endif
#include "typeinfo.h"
#include "stdio.h"
#include "tchar.h"
#include "JList.h"
//---------------------------------------------------------------------------------------------
//调试信息输出宏
//功能:如果定义了 JCREATEINST_DEBUG ,则每当分配或释放内存时,就像控制台输出信息
// 开发者可以根据这些信息察看是否有内存泄漏
//---------------------------------------------------------------------------------------------
#ifdef JCREATEINST_DEBUG
#ifdef UNICODE
#define PRINT_MEM_MESSAGE( ulDimension , ptr , iMemType ) \
{ \
int iLength = mbstowcs( NULL , typeid( * ptr ).name() , 0 ) ; \
wchar_t * lpwcString = new wchar_t [ iLength + 1 ] ; \
mbstowcs( lpwcString , typeid( * ptr ).name() , strlen( typeid( * ptr ).name() ) + 1 ) ; \
_tprintf( _T( "%s %s%s : %#.8x\n" ) , ( iMemType == 1 ) ? _T( "new" ) : ( iMemType == 0 ? _T( "delete" ) : _T( "attach" ) ) , lpwcString , ( ulDimension > 1 ) ? _T( "[]" ) : _T( "" ) , ( ptr ) ) ; \
delete [] lpwcString ; \
}
#else
#define PRINT_MEM_MESSAGE( ulDimension , ptr , iMemType ) \
_tprintf( _T( "%s %s%s : %#.8x\n" ) , ( iMemType == 1 ) ? _T( "new" ) : ( iMemType == 0 ? _T( "delete" ) : _T( "attach" ) ) , typeid( * ptr ).name() , ( ulDimension > 1 ) ? _T( "[]" ) : _T( "" ) , ( ptr ) ) ;
#endif
#else
#define PRINT_MEM_MESSAGE( ulDimension , ptr , iMemType )
#endif
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//一些用户定义智能指针的宏
//最好使用这些宏来定义智能指针,这样比较好理解
//如果有特殊要求就直接使用类 JCreateInst 定义智能指针
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------------------------
//功能说明:新建一个 T * 类型的 NULL 智能指针
//---------------------------------------------------------------------------------------------
//使用举例:smart_new( int , lpiInt ) ; //在用户眼中:int * lpiInt = new int ;
// lpiInt = smart_null( int ) ; //在用户眼中:lpiInt = NULL ;
// // lpiInt 原先指向的内存必要时会自动释放掉
//---------------------------------------------------------------------------------------------
#define smart_null( T ) \
JCreateInst<T>( 0L )
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_null( int , lpiInt ) ; //在用户眼中:int * lpiInt = NULL ;
// lpiInt = new int ; // lpiInt 得到指针后并不自动释放内存
//---------------------------------------------------------------------------------------------
#define smart_new_null( T , var ) \
JCreateInst<T> var
//---------------------------------------------------------------------------------------------
//功能说明:新建一个 T * 类型的 NULL 智能指针数组
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_null_array( int , lpiInt , 10 ) ; //在用户眼中:int * lpiInt[ 10 ] = { NULL } ;
// for( int i = 0 ; i < 10 ; i ++ )
// lpiInt[ i ] = new int ; // lpiInt[ i ] 得到指针后并不自动释放内存
//---------------------------------------------------------------------------------------------
#define smart_new_null_array( T , var , ulDimension ) \
JCreateInst<T> var[ ulDimension ]
//---------------------------------------------------------------------------------------------
//功能说明:新建一个智能指针,指向单个 T 实例(不带参数)
// 实用于 C 语言内建的基本数据类型和 C++ 中构造函数不带参数的类
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_null( int , lpiInt ) ; //在用户眼中:int * lpiInt = NULL ;
// lpiInt = smart( int ) ; //在用户眼中:lpiInt = new int ;
// * lpiInt = 911 ; // lpiInt 指向的内存会自动释放
//---------------------------------------------------------------------------------------------
#define smart( T ) \
JCreateInst<T>( 1L )
//---------------------------------------------------------------------------------------------
//使用举例:smart_new( int , lpiInt ) ; //在用户眼中:int * lpiInt = new int ;
// * lpiInt = 911 ; // lpiInt 指向的内存会自动释放
//---------------------------------------------------------------------------------------------
#define smart_new( T , var ) \
JCreateInst<T> var( 1L )
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_modifier( extern , int , lpiInt ) ; //在用户眼中:extern int * lpiInt ;
// lpiInt = smart( int ) ; //在用户眼中:lpiInt = new int ;
// * lpiInt = 911 ; // lpiInt 指向的内存会自动释放
//---------------------------------------------------------------------------------------------
#define smart_new_modifier( Modifier , T , var ) \
Modifier JCreateInst<T> var
//---------------------------------------------------------------------------------------------
//使用举例:smart_new( int , lpiInt1 ) ; //在用户眼中:int * lpiInt1 = new int ;
// smart_assign( int , lpiInt2 , lpiInt1 ) ; //在用户眼中:int * lpiInt2 = lpiInt1 ;
// * lpiInt2 = 911 ; // lpiInt1 与 lpiInt2 指向同一块内存,会正确自动释放
//---------------------------------------------------------------------------------------------
#define smart_assign( T , var1 , var2 ) \
JCreateInst<T> var1( var2 )
//---------------------------------------------------------------------------------------------
//使用举例:smart_new( int , lpiInt1 ) ; //在用户眼中:int * lpiInt1 = new int ;
// smart_attach( lpiInt1 , new int , false ) ; //在用户眼中:lpiInt1 = new int ;
// * lpiInt1 = 911 ; // lpiInt1 曾指向的所有内存,都会正确自动释放
//---------------------------------------------------------------------------------------------
#define smart_attach( var , ptr , bMultiDimension ) \
var.AttachPtr( ptr , bMultiDimension )
//---------------------------------------------------------------------------------------------
//功能说明:新建一个智能指针,指向 T 实例数组(不带参数)
// 实用于 C 语言内建的基本数据类型和 C++ 中构造函数不带参数的类
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_null( int , lpiInt ) ; //在用户眼中:int * lpiInt = NULL ;
// lpiInt = smart_array( int , 10 ) ; //在用户眼中:lpiInt = new int [ 10 ] ;
// for( int i = 0 ; i < 10 ; i ++ )
// lpiInt[ i ] = i ;
//---------------------------------------------------------------------------------------------
#define smart_array( T , ulDimension ) \
JCreateInst<T>( static_cast< long >( ulDimension ) )
//---------------------------------------------------------------------------------------------
//使用举例:smart_new_array( int , lpiInt , 10 ) ; //在用户眼中:int * lpiInt = new int [ 10 ] ;
// for( int i = 0 ; i < 10 ; i ++ )
// lpiInt[ i ] = i ;
//---------------------------------------------------------------------------------------------
#define smart_new_array( T , var , ulDimension ) \
JCreateInst<T> var( static_cast< long >( ulDimension ) )
//---------------------------------------------------------------------------------------------
//功能说明:新建一个智能指针,指向单个 T 实例(可以指定参数)
// 只适用于 C++ 中构造函数带参数的类型
//使用举例:// A 是一个类,构造函数需要两个参数
// smart_new_null( A , lpaA ) ; //在用户眼中:A * lpaA = NULL ;
// lpaA = smart_params( A , A( 12 , "temp" ) ) ; //在用户眼中:lpaA = new A( 12 , "temp" ) ;
// lpaA->...
//---------------------------------------------------------------------------------------------
#define smart_params( T , C ) \
JCreateInst<T>( new C , 1L )
//---------------------------------------------------------------------------------------------
//使用举例:// A 是一个类,构造函数需要两个参数
// smart_new_params( A , lpaA , A( 12 , "temp" ) ) ; //在用户眼中:A * lpaA = new A( 12 , "temp" ) ;
// lpaA->... // lpaA 指向的内存会自动释放
//---------------------------------------------------------------------------------------------
#define smart_new_params( T , var , C ) \
JCreateInst<T> var( new C , 1L )
//---------------------------------------------------------------------------------------------
//功能说明:新建一个智能指针,指向 T 实例数组(可以指定参数)
// 只适用于 C++ 中构造函数带参数的类型
//---------------------------------------------------------------------------------------------
//使用举例:// A 是一个类,构造函数需要两个参数
// smart_new_array_params( A , lplpaA , A( 12 , "temp" ) , 10 ) ; //在用户眼中:A ** lplpaA = new A * [ 10 ] ;
// // for( int i = 0 ; i < 10 ; i ++ )
// // lplpaA[ i ] = new A( 12 , "temp" ) ;
// lplpaA[ 0 ]->...
//---------------------------------------------------------------------------------------------
#define smart_new_array_params( T , var , C , ulDimension ) \
JCreateInst<T> var[ ulDimension ] ; \
{ \
for( int i = 0 ; i < ( ulDimension ) ; i ++ ) \
var[ i ] = JCreateInst<T>( new C , 1L ) ; \
}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//一些全局变量
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------------------------
//不合法指针(在链表中已经删除的指针)
//---------------------------------------------------------------------------------------------
#define INVALID_PTR 0xFFFFFFFF
//---------------------------------------------------------------------------------------------
//存储类型为 T 的所有 PTRANDREF 指针的全局链表
//注意:千万不能将此变量放在类 JCreateInst 中作为一个静态变量,如果这样做,
// 当用户定义一个 JCreateInst 类型的全局变量时肯定会出现内存访问错误
//---------------------------------------------------------------------------------------------
extern JList * g_lpjlTJList ;
//---------------------------------------------------------------------------------------------
//存储类 JCreateInst 构造(包括复制构造)的次数(不管 T 如何)
//---------------------------------------------------------------------------------------------
extern unsigned long g_ulJCreateInstConstructedCount ;
//---------------------------------------------------------------------------------------------
//存储链表 g_lpjlTJList 中无效(值为 INVALID_PTR --- 0xFFFFFFFF )的索引
//---------------------------------------------------------------------------------------------
extern JList * g_lpjlT_INVALID_PTR_JList ;
#ifdef JCREATEINST_MULTI_THREAD
//---------------------------------------------------------------------------------------------
//全局关键区,控制多线程对全局变量 g_lpjlTJList , g_ulJCreateInstConstructedCount 的访问
//---------------------------------------------------------------------------------------------
extern CRITICAL_SECTION g_csJCreateInstCriticalSection ;
//---------------------------------------------------------------------------------------------
//类声明,禁止用户构造此类的任何实例
//用途:初始化和删除“全局关键区---g_csJCreateInstCriticalSection”
//---------------------------------------------------------------------------------------------
extern bool sg_bInitialized ;
class InitAndDelJCreateInstCriticalSection
{
public :
InitAndDelJCreateInstCriticalSection( void )
{
this->InitJCreateInstCriticalSection() ;
}
static void InitJCreateInstCriticalSection( void )
{
if( ! ::sg_bInitialized )
{
#ifdef JCREATEINST_DEBUG
_tprintf( _T( "Initialize CriticalSection!\n" ) ) ;
#endif
::InitializeCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
::sg_bInitialized = true ;
}
}
~InitAndDelJCreateInstCriticalSection( void )
{
if( ::sg_bInitialized )
{
::DeleteCriticalSection( & g_csJCreateInstCriticalSection ) ;
::sg_bInitialized = false ;
#ifdef JCREATEINST_DEBUG
_tprintf( _T( "Uninitialize CriticalSection!\n" ) ) ;
#endif
}
}
} ;
//---------------------------------------------------------------------------------------------
//全局静态变量,此变量不能使用
//用途:通过调用构造函数和析构函数来初始化和删除“全局关键区---g_csJCreateInstCriticalSection”
//---------------------------------------------------------------------------------------------
extern InitAndDelJCreateInstCriticalSection sg_Temp ;
#endif
//---------------------------------------------------------------------------------------------
//类 PTRANDREF 定义,存储了每一个动态分配的内存地址以及引用值、维数
//---------------------------------------------------------------------------------------------
template<class T>
class PTRANDREF
{
public :
//---------------------------------------------------------------------------------------------
//存储类型 T 的基指针(这个指针的值是不允许改变的)
//---------------------------------------------------------------------------------------------
T * m_lptInstBasePtr ;
//---------------------------------------------------------------------------------------------
//存储指针 this->m_lptInstBasePtr 被引用的次数
//---------------------------------------------------------------------------------------------
unsigned long m_ulRefCount ;
//---------------------------------------------------------------------------------------------
//存储指针 this->m_lptInstBasePtr 所指向的数组维数
//如果为 0 ,说明指针 this->m_lptInstBasePtr 指向单个元素 T
//---------------------------------------------------------------------------------------------
unsigned long m_ulDimension ;
} ;
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//类 JCreateInst 的定义
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
template < class T >
class JCreateInst
{
//私有成员
private :
//---------------------------------------------------------------------------------------------
//存储此类所对应的内存指针在链表 g_lpjlTJList 中的索引
//---------------------------------------------------------------------------------------------
int m_iIndexInList ;
//---------------------------------------------------------------------------------------------
//存储类型 T 的存取指针(这个指针的值是允许改变,用户存取值均使用此指针)
//---------------------------------------------------------------------------------------------
T * m_lptInstPtr ;
//---------------------------------------------------------------------------------------------
//构造函数处理(因为不光构造函数中会用到此函数,所以将其单独列成一个函数)
//---------------------------------------------------------------------------------------------
void Construct( unsigned long ulDimension )
{
#ifdef JCREATEINST_MULTI_THREAD
//必须要判断 “全局关键区 g_csJCreateInstCriticalSection ” 是否初始化
//原因:如果用户在程序中定义了全局的 JCreateInst<T> 实例 t ,有可能
// t 在 sg_Temp 之前定义,这时 “全局关键区” 并没有初始化,需要
// 此时初始化,当全局变量 sg_Temp 定义时,它的构造函数便不会再初
// 始化 “全局关键区”
InitAndDelJCreateInstCriticalSection::InitJCreateInstCriticalSection() ;
//进入全局关键区,如果全局关键区被其他线程占用则一直等待到得到拥有权为止
::EnterCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
if( ! g_ulJCreateInstConstructedCount ++ )
{
g_lpjlTJList = new JList() ;
g_lpjlT_INVALID_PTR_JList = new JList() ;
//预设空间大小,避免一开始时频繁的重新分配内存
g_lpjlTJList->SetCapacity( 128 ) ;
g_lpjlT_INVALID_PTR_JList->SetCapacity( 128 ) ;
PRINT_MEM_MESSAGE( 0 , g_lpjlTJList , 1 ) ;
PRINT_MEM_MESSAGE( 0 , g_lpjlT_INVALID_PTR_JList , 1 ) ;
}
if( ! ulDimension )
this->m_lptInstPtr = NULL ;
else if( ulDimension == 1 )
this->m_lptInstPtr = new T ;
else
this->m_lptInstPtr = new T [ ulDimension ] ;
unsigned long ulRefCount = 1 ;
//将链表 g_lpjlTJList 中指针为 this->m_lptInstPtr 的项的引用计数增加一
//主要是为了 this->m_lptInstPtr == NULL 的情况,因为链表中 NULL 指针可能早已经存在了
//但是也不排除非 NULL 指针也已经存在:比如用户先前强行指定了一个指针 ptr 与某个 JCreateInst
//类链接(也就是说由类来释放内存),现在动态分配的内存 this->m_lptInstPtr 有恰好等于 ptr
//这时,下面的循环就显得很有必要了
for( int i = 0 ; i < g_lpjlTJList->GetCount() ; i ++ )
{
//这里存在强制转换,因为 g_lpjlTJList->Items[ i ] 不一定是 PTRANDREF<T> * 类型的指针(可能 T 不同)
if( g_lpjlTJList->Items[ i ] != ( void * ) INVALID_PTR
&& ( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ i ] ) )->m_lptInstBasePtr == this->m_lptInstPtr )
{
ulRefCount = ++ ( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ i ] ) )->m_ulRefCount ;
this->m_iIndexInList = i ;
//维数以新的为准
( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ i ] ) )->m_ulDimension = ulDimension ;
break ;
}
}
//如果链表中没有指针 this->m_lptInstPtr
if( ulRefCount == 1 )
{
PTRANDREF<T> * lpparPtrAndRefTemp = new PTRANDREF<T> ;
lpparPtrAndRefTemp->m_lptInstBasePtr = this->m_lptInstPtr ;
lpparPtrAndRefTemp->m_ulRefCount = ulRefCount ;
lpparPtrAndRefTemp->m_ulDimension = ulDimension ;
if( g_lpjlT_INVALID_PTR_JList->GetCount() )
{
//重新利用链表 g_lpjlTJList 中的无效节点
this->m_iIndexInList = int( g_lpjlT_INVALID_PTR_JList->Items[ 0 ] ) ;
g_lpjlTJList->Items[ int( g_lpjlT_INVALID_PTR_JList->Items[ 0 ] ) ] = lpparPtrAndRefTemp ;
//从链表中删除此索引
g_lpjlT_INVALID_PTR_JList->Delete( 0 ) ;
}
else
this->m_iIndexInList = g_lpjlTJList->Add( lpparPtrAndRefTemp ) ;
}
PRINT_MEM_MESSAGE( ulDimension , this->m_lptInstPtr , 1 ) ;
#ifdef JCREATEINST_MULTI_THREAD
//离开全局关键区,释放对全局关键区的拥有权
::LeaveCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
}
//---------------------------------------------------------------------------------------------
//链接外来指针(因为不光复制构造函数中会用到此函数,所以将其单独列成一个函数)
//将外来指针视为此类动态分配的,并保证其自动释放
//---------------------------------------------------------------------------------------------
void AttachOtherPtr( T * lptTPtr , unsigned long ulDimension = 0 )
{
#ifdef JCREATEINST_MULTI_THREAD
//必须要判断 “全局关键区 g_csJCreateInstCriticalSection ” 是否初始化
//原因:如果用户在程序中定义了全局的 JCreateInst<T> 实例 t ,有可能
// t 在 sg_Temp 之前定义,这时 “全局关键区” 并没有初始化,需要
// 此时初始化,当全局变量 sg_Temp 定义时,它的构造函数便不会再初
// 始化 “全局关键区”
InitAndDelJCreateInstCriticalSection::InitJCreateInstCriticalSection() ;
//进入全局关键区,如果全局关键区被其他线程占用则一直等待到得到拥有权为止
::EnterCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
if( ! g_ulJCreateInstConstructedCount ++ )
{
g_lpjlTJList = new JList() ;
g_lpjlT_INVALID_PTR_JList = new JList() ;
//预设空间大小,避免一开始时频繁的重新分配内存
g_lpjlTJList->SetCapacity( 128 ) ;
g_lpjlT_INVALID_PTR_JList->SetCapacity( 128 ) ;
PRINT_MEM_MESSAGE( 0 , g_lpjlTJList , 1 ) ;
PRINT_MEM_MESSAGE( 0 , g_lpjlT_INVALID_PTR_JList , 1 ) ;
}
this->m_lptInstPtr = lptTPtr ;
unsigned long ulRefCount = 1 ;
//将链表 g_lpjlTJList 中指针为 this->m_lptInstPtr 的项的引用计数增加一
//主要是为了 this->m_lptInstPtr == NULL 的情况,因为链表中 NULL 指针可能早已经存在了
//但是也不排除非 NULL 指针也已经存在:比如用户先前强行指定了一个指针 ptr 与某个 JCreateInst
//类链接(也就是说由类来释放内存),现在动态分配的内存 this->m_lptInstPtr 有恰好等于 ptr
//这时,下面的循环就显得很有必要了
for( int i = 0 ; i < g_lpjlTJList->GetCount() ; i ++ )
{
//这里存在强制转换,因为 g_lpjlTJList->Items[ i ] 不一定是 PTRANDREF<T> * 类型的指针(可能 T 不同)
if( g_lpjlTJList->Items[ i ] != ( void * ) INVALID_PTR
&& ( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ i ] ) )->m_lptInstBasePtr == this->m_lptInstPtr )
{
ulRefCount = ++ ( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ i ] ) )->m_ulRefCount ;
this->m_iIndexInList = i ;
break ;
}
}
//如果链表中没有指针 this->m_lptInstPtr
if( ulRefCount == 1 )
{
PTRANDREF<T> * lpparPtrAndRefTemp = new PTRANDREF<T> ;
lpparPtrAndRefTemp->m_lptInstBasePtr = this->m_lptInstPtr ;
lpparPtrAndRefTemp->m_ulRefCount = ulRefCount ;
lpparPtrAndRefTemp->m_ulDimension = ulDimension ;
if( g_lpjlT_INVALID_PTR_JList->GetCount() )
{
//重新利用链表 g_lpjlTJList 中的无效节点
this->m_iIndexInList = int( g_lpjlT_INVALID_PTR_JList->Items[ 0 ] ) ;
g_lpjlTJList->Items[ int( g_lpjlT_INVALID_PTR_JList->Items[ 0 ] ) ] = lpparPtrAndRefTemp ;
//从链表中删除此索引
g_lpjlT_INVALID_PTR_JList->Delete( 0 ) ;
}
else
this->m_iIndexInList = g_lpjlTJList->Add( lpparPtrAndRefTemp ) ;
}
PRINT_MEM_MESSAGE( ulDimension , lptTPtr , -1 ) ;
#ifdef JCREATEINST_MULTI_THREAD
//离开全局关键区,释放对全局关键区的拥有权
::LeaveCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
}
//---------------------------------------------------------------------------------------------
//复制构造处理(因为不光复制构造函数中会用到此函数,所以将其单独列成一个函数)
//---------------------------------------------------------------------------------------------
void CopyConstruct( const JCreateInst<T> & jciJCreateInst )
{
#ifdef JCREATEINST_MULTI_THREAD
if( ::sg_bInitialized )
//进入全局关键区,如果全局关键区被其他线程占用则一直等待到得到拥有权为止
::EnterCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
#ifdef JCREATEINST_DEBUG
//_tprintf( _T( "Copy Construct JCreateInst no new instance created! %x\n" ) , jciJCreateInst.m_lptInstPtr ) ;
#endif
//不需要判断 g_lpjlTJList 是否需要分配内存
//因为参数 jciJCreateInst 的存在就说明了 g_lpjlTJList 已经分配了内存
g_ulJCreateInstConstructedCount ++ ;
this->m_iIndexInList = jciJCreateInst.m_iIndexInList ;
this->m_lptInstPtr = jciJCreateInst.m_lptInstPtr ;
//将链表 g_lpjlTJList 中第 this->m_iIndexInList 项的引用计数增加一
( ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ this->m_iIndexInList ] ) )->m_ulRefCount ++ ;
#ifdef JCREATEINST_MULTI_THREAD
if( ::sg_bInitialized )
//离开全局关键区,释放对全局关键区的拥有权
::LeaveCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
}
//---------------------------------------------------------------------------------------------
//析构处理(因为不光析构函数中会用到此函数,所以将其单独列成一个函数)
//---------------------------------------------------------------------------------------------
void Destroy( void )
{
#ifdef JCREATEINST_MULTI_THREAD
if( ::sg_bInitialized )
//进入全局关键区,如果全局关键区被其他线程占用则一直等待到得到拥有权为止
::EnterCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
#ifdef JCREATEINST_DEBUG
//_tprintf( _T( "JCreateInst destructed! %x\n" ) , this->m_lptInstPtr ) ;
#endif
//将链表 g_lpjlTJList 中第 this->m_iIndexInList 项的引用计数减少一
//这里存在强制转换,因为 g_lpjlTJList->Items[ i ] 不一定是 PTRANDREF<T> * 类型的指针(可能 T 不同)
PTRANDREF<T> * lpparPtrAndRefTemp = ( PTRANDREF<T> * ) ( g_lpjlTJList->Items[ this->m_iIndexInList ] ) ;
if( ! ( -- lpparPtrAndRefTemp->m_ulRefCount ) )
{
//释放内存
if( lpparPtrAndRefTemp->m_ulDimension > 1 )
{
delete [] lpparPtrAndRefTemp->m_lptInstBasePtr ;
PRINT_MEM_MESSAGE( lpparPtrAndRefTemp->m_ulDimension , lpparPtrAndRefTemp->m_lptInstBasePtr , 0 ) ;
}
else if( lpparPtrAndRefTemp->m_ulDimension == 1 )
{
delete lpparPtrAndRefTemp->m_lptInstBasePtr ;
PRINT_MEM_MESSAGE( lpparPtrAndRefTemp->m_ulDimension , lpparPtrAndRefTemp->m_lptInstBasePtr , 0 ) ;
}
else // lpparPtrAndRefTemp->m_ulDimension == 0 的情况,说明 lpparPtrAndRefTemp->m_lptInstBasePtr == NULL
{
PRINT_MEM_MESSAGE( lpparPtrAndRefTemp->m_ulDimension , lpparPtrAndRefTemp->m_lptInstBasePtr , 0 ) ;
}
//释放链表中此项所占内存
delete lpparPtrAndRefTemp ;
//从链表中删除此项(不能真正的删除,否则会影响其它类的索引有效性)
//将此项设为 INVALID_PTR ,因为动态分配的内存不可能位于此处
g_lpjlTJList->Items[ this->m_iIndexInList ] = ( void * ) INVALID_PTR ;
//将此无效索引添加到链表 g_lpjlT_INVALID_PTR_JList 中,以备使用
g_lpjlT_INVALID_PTR_JList->Add( ( void * ) this->m_iIndexInList ) ;
}
//判断是否需要释放链表的内存
if( ! -- g_ulJCreateInstConstructedCount )
{
PRINT_MEM_MESSAGE( 0 , g_lpjlTJList , 0 ) ;
PRINT_MEM_MESSAGE( 0 , g_lpjlT_INVALID_PTR_JList , 0 ) ;
delete g_lpjlTJList ;
delete g_lpjlT_INVALID_PTR_JList ;
g_lpjlTJList = NULL ;
g_lpjlT_INVALID_PTR_JList = NULL ;
}
#ifdef JCREATEINST_MULTI_THREAD
if( ::sg_bInitialized )
//离开全局关键区,释放对全局关键区的拥有权
::LeaveCriticalSection( & ::g_csJCreateInstCriticalSection ) ;
#endif
}
//公有成员
public :
//---------------------------------------------------------------------------------------------
//构造函数 1
//---------------------------------------------------------------------------------------------
/* explicit JCreateInst( unsigned int uiDimension )
{
this->Construct( ( unsigned long ) uiDimension ) ;
}*/
//---------------------------------------------------------------------------------------------
//构造函数 2
//---------------------------------------------------------------------------------------------
//参数说明:iDimension --- 默认值为 0 ,构造一个 NULL 指针,没有实际分配
// 内存
// --- 如果为 1 , 为一个 T 分配内存
// --- 如果大于 1 ,为 iDimension 个 T 分配内存
//---------------------------------------------------------------------------------------------
/* explicit JCreateInst( int iDimension = 0 )
{
this->Construct( ( unsigned long ) ( iDimension < 0 ? 0 : iDimension ) ) ;
}*/
//---------------------------------------------------------------------------------------------
//构造函数 3
//---------------------------------------------------------------------------------------------
/* explicit JCreateInst( unsigned long ulDimension )
{
this->Construct( ulDimension ) ;
}*/
//---------------------------------------------------------------------------------------------
//构造函数 4
//---------------------------------------------------------------------------------------------
explicit JCreateInst( long lDimension )
{
this->Construct( ( unsigned long ) ( lDimension < 0 ? 0 : lDimension ) ) ;
}
//---------------------------------------------------------------------------------------------
//copy constructor
//---------------------------------------------------------------------------------------------
JCreateInst( const JCreateInst<T> & jciJCreateInst )
{
this->CopyConstruct( jciJCreateInst ) ;
}
//---------------------------------------------------------------------------------------------
//析构函数
//---------------------------------------------------------------------------------------------
~JCreateInst( void )
{
this->Destroy() ;
}
//---------------------------------------------------------------------------------------------
//算符 = 重载 1
//---------------------------------------------------------------------------------------------
JCreateInst & operator =( JCreateInst<T> jciJCreateInst )
{
//执行析构的所有语句
this->Destroy() ;
//执行复制构造的所有语句
this->CopyConstruct( jciJCreateInst ) ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 -> 重载
//---------------------------------------------------------------------------------------------
T * operator ->( void )
{
return this->m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 * 重载
//---------------------------------------------------------------------------------------------
T & operator *( void )
{
return * this->m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 + 重载
//---------------------------------------------------------------------------------------------
JCreateInst operator +( int i )
{
JCreateInst<T> ciTemp = * this ;
ciTemp.m_lptInstPtr += i ;
return ciTemp ;
}
//---------------------------------------------------------------------------------------------
//算符 += 重载
//---------------------------------------------------------------------------------------------
JCreateInst & operator +=( int i )
{
this->m_lptInstPtr += i ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 ++ 重载
//---------------------------------------------------------------------------------------------
JCreateInst & operator ++( void )
{
this->m_lptInstPtr ++ ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 ++( int ) 重载
//---------------------------------------------------------------------------------------------
const JCreateInst operator ++( int )
{
JCreateInst<T> ciTemp = * this ;
++ ( * this ) ;
return ciTemp ;
}
//---------------------------------------------------------------------------------------------
//算符 - 重载 1
//---------------------------------------------------------------------------------------------
JCreateInst operator -( int i )
{
JCreateInst<T> ciTemp = * this ;
ciTemp.m_lptInstPtr -= i ;
return ciTemp ;
}
//---------------------------------------------------------------------------------------------
//算符 - 重载 2
//---------------------------------------------------------------------------------------------
long operator -( JCreateInst<T> & ciTemp )
{
return long( this->m_lptInstPtr - ciTemp.m_lptInstPtr ) ;
}
//---------------------------------------------------------------------------------------------
//算符 -= 重载
//---------------------------------------------------------------------------------------------
JCreateInst & operator -=( int i )
{
this->m_lptInstPtr -= i ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 -- 重载
//---------------------------------------------------------------------------------------------
JCreateInst & operator --( void )
{
this->m_lptInstPtr -- ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 --( int ) 重载
//---------------------------------------------------------------------------------------------
const JCreateInst operator --( int )
{
JCreateInst<T> ciTemp = * this ;
-- ( * this ) ;
return ciTemp ;
}
//---------------------------------------------------------------------------------------------
//算符 [] 重载
//---------------------------------------------------------------------------------------------
T & operator []( int iIndex )
{
return * ( this->m_lptInstPtr + iIndex ) ;
}
//---------------------------------------------------------------------------------------------
//算符 ! 重载
//---------------------------------------------------------------------------------------------
bool operator !( void )
{
return this->m_lptInstPtr == NULL ;
}
//---------------------------------------------------------------------------------------------
//算符 == 重载 1
//---------------------------------------------------------------------------------------------
bool operator ==( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr == jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 == 重载 2
//---------------------------------------------------------------------------------------------
bool operator ==( T * lptTPtr )
{
return this->m_lptInstPtr == lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 != 重载 1
//---------------------------------------------------------------------------------------------
bool operator !=( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr != jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 != 重载 2
//---------------------------------------------------------------------------------------------
bool operator !=( T * lptTPtr )
{
return this->m_lptInstPtr != lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 < 重载 1
//---------------------------------------------------------------------------------------------
bool operator <( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr < jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 < 重载 2
//---------------------------------------------------------------------------------------------
bool operator <( T * lptTPtr )
{
return this->m_lptInstPtr < lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 > 重载 1
//---------------------------------------------------------------------------------------------
bool operator >( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr > jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 > 重载 2
//---------------------------------------------------------------------------------------------
bool operator >( T * lptTPtr )
{
return this->m_lptInstPtr > lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 <= 重载 1
//---------------------------------------------------------------------------------------------
bool operator <=( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr <= jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 <= 重载 2
//---------------------------------------------------------------------------------------------
bool operator <=( T * lptTPtr )
{
return this->m_lptInstPtr <= lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 >= 重载 1
//---------------------------------------------------------------------------------------------
bool operator >=( JCreateInst<T> jciJCreateInst )
{
return this->m_lptInstPtr >= jciJCreateInst.m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 >= 重载 2
//---------------------------------------------------------------------------------------------
bool operator >=( T * lptTPtr )
{
return this->m_lptInstPtr >= lptTPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 int() 重载
//---------------------------------------------------------------------------------------------
operator int( void )
{
return int( this->m_lptInstPtr ) ;
}
//---------------------------------------------------------------------------------------------
//算符 unsigned int() 重载
//---------------------------------------------------------------------------------------------
operator unsigned int( void )
{
return ( unsigned int ) ( this->m_lptInstPtr ) ;
}
//---------------------------------------------------------------------------------------------
//算符 long() 重载
//---------------------------------------------------------------------------------------------
operator long( void )
{
return long( this->m_lptInstPtr ) ;
}
//---------------------------------------------------------------------------------------------
//算符 unsigned long() 重载
//---------------------------------------------------------------------------------------------
operator unsigned long( void )
{
return ( unsigned long ) ( this->m_lptInstPtr ) ;
}
//---------------------------------------------------------------------------------------------
//算符 bool() 重载
//---------------------------------------------------------------------------------------------
operator bool( void )
{
return this->m_lptInstPtr != NULL ;
}
//---------------------------------------------------------------------------------------------
//算符 new() 重载
//重载此操作符是为了禁止用户动态创建此类
//---------------------------------------------------------------------------------------------
//一次修订
//说明:将此函数注释掉是为了确保正确的与各种标准模板容器交互使用
//---------------------------------------------------------------------------------------------
// void * operator new( size_t stSize )
// {
// return NULL ;
// }
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
//算符 new[]() 重载
//重载此操作符是为了禁止用户动态创建此类数组
//---------------------------------------------------------------------------------------------
//一次修订
//说明:将此函数注释掉是为了确保正确的与各种标准模板容器交互使用
//---------------------------------------------------------------------------------------------
// void * operator new[]( size_t stSize )
// {
// return NULL ;
// }
//---------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//以下是一些比较危险的函数(由于误用有可能导致内存泄漏),请按照说明使用
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------------------------
//构造函数 0
//---------------------------------------------------------------------------------------------
//使用前提:用户想创建一个指定指针 lptTPtr 的类(在用户眼中此类就是一个
// T * 指针)。
//使用方法:构造此类的时候指定一个 T * 参数
//使用注意:如果用户需要此类自动释放内存,用户要保证 lptTPtr 指向的是动
// 态分配的内存。
// 例如:T t ;
// T * lptTPtr = & t ;
// 如果此类尝试去释放 lptTPtr 指向的内存则必然会引起错误。
//附带说明:1. 如果 ulDimension = 0 ,用户将 lptTPtr 与此类链接后应该自
// 己负责释放 lptTPtr 指向的内存。
// 2. 如果 ulDimension > 0 ,用户将 lptTPtr 与此类链接后禁止
// 释放 lptTPtr 指向的内存,而是由此类自动释放。
// 如果 ulDimension = 1 ,说明是普通指针
// 如果 ulDimension > 1 ,说明是数组指针
// 3. 看下面的语句,他们是等价的:
// JCreateInst<int> lpiInt ; | int * lpiTemp = new int ;
// int * lpiTemp = new int ; | JCreateInst<int> lpiInt( lpiTemp , 0 ) ;
// lpiInt = lpiTemp ; | delete lpiTemp ;
// delete lpiTemp ; |
//---------------------------------------------------------------------------------------------
explicit JCreateInst( T * lptTPtr , unsigned long ulDimension )
{
if( ! ulDimension ) //如果维数为 0 ,则只是简单的将 lptTPtr 链接到
//此类,并不自动释放 lptTPtr 指向的内存
{
this->Construct( 0L ) ; //先构造一个空指针
this->m_lptInstPtr = lptTPtr ;
}
else //如果维数不为 0 ,则将 lptTPtr 链接到此类,并且自动释放 lptTPtr
//指向的内存
this->AttachOtherPtr( lptTPtr , ulDimension ) ;
}
//---------------------------------------------------------------------------------------------
//算符 T *() 重载
//---------------------------------------------------------------------------------------------
//参数说明:lptTPtr ------ 想要 attach 的指针
// bMultiDimension ------ 表明 lptTPtr 是否为指向多维数组的指针
//---------------------------------------------------------------------------------------------
JCreateInst<T> & AttachPtr( T * lptTPtr , bool bMultiDimension = false )
{
this->Destroy() ;
this->AttachOtherPtr( lptTPtr , bMultiDimension ? 2 : 1 ) ;
return * this ;
}
//---------------------------------------------------------------------------------------------
//算符 T *() 重载
//---------------------------------------------------------------------------------------------
//使用前提:当用户需要将此类(在用户眼中此类就是一个 T * 指针)赋值给另外
// 一个 T * 类型的变量时(不管有没有显式的作类型转换)编译器会调
// 用此函数。
//使用方法:通过类型转换得到类型为 T * 的指针后马上使用它,保证在此类析构
// 以前使用完毕,这样就不会出现任何问题。
//使用注意:1. 如果用户将得到的指针 ptr 保存起来以备后用,则有能出现内存
// 访问违规的错误:因为用户不知道什么时候 ptr 被释放掉。
// 2. 用户对得到的指针 ptr 无论做何修改都没有关系,不会对此类产
// 生任何影响
//附带说明:其实如果用户将此类(在用户眼中此类就是一个 T * 指针)转化为
// void * 类型编译器同样会调用此函数,因为编译器将 void * 视为任
// 何类型的指针
//---------------------------------------------------------------------------------------------
operator T *( void )
{
return this->m_lptInstPtr ;
}
//---------------------------------------------------------------------------------------------
//算符 & 重载
//---------------------------------------------------------------------------------------------
//使用前提:用户想获得此类(在用户眼中此类就是一个 T * 指针)代表的 T * 指针的地址
//使用方法:使用 & 取址操作符取地址,通过类型转换得到类型为 T * 的指针后马上使用它,
// 保证在此类析构以前使用完毕,这样就不会出现任何问题。
//使用注意:1. 如果用户将得到的指针地址 lplpPtr 保存起来以备后用,则有能出现内存
// 访问违规的错误:因为用户不知道什么时候 * lplpPtr 被释放掉。
// 2. 用户对得到的指针地址指向的值 * lplpPtr 无论做何修改都没有关系,不会
// 对此类产生任何影响
//附带说明:
//---------------------------------------------------------------------------------------------
//一次修订
//修订说明:将此函数注释掉是为了确保正确的与各种标准模板容器交互使用
// 原因:在使用 C++Builder6 提供的 STL 库的标准类 vector 进行测试时发现
// 无法正确析购此类实例,请看以下代码:
// void main()
// {
// using namespace std ;
//
// vector< JCreateInst< int > > v ;
//
// for( int i = 0 ; i < 100 ; i ++ )
// v.push_back( smart( int ) ) ;
// }
// 当以上程序退出时每个 JCreateInst< int > 实例的析构函数并没有调用
// 究其原因发现: C++Builder6 提供的模板类 vector 在自身析构时依次调用
// 容器内的每个元素的析构函数,代码如下:
//
// File <_construct.h>
//
// template <class _ForwardIterator>
// _STLP_INLINE_LOOP void
// __destroy_aux(_ForwardIterator __first, _ForwardIterator __last, const __false_type&) {
// for ( ; __first != __last; ++__first)
// _Destroy(&*__first);
// }
//
// 以上这段代码之所以不能正确析构 JCreateInst< int > 的关键在于:
// _Destroy(&*__first);
// 上面这行代码对于重载了 & 算符的模板类 JCreateInst< T > 的任何实例都不会得到
// 得到正确的结果!
//附带说明:在 VC++6 中,即使算符 & 被重载了,以上程序照常释放所有内存。
//---------------------------------------------------------------------------------------------
// T ** operator &( void )
// {
// return & ( this->m_lptInstPtr ) ;
// }
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
//算符 = 重载 2
//---------------------------------------------------------------------------------------------
//使用前提:用户想改变此类(在用户眼中此类就是一个 T * 指针)的值,将一个
// 类型为 T * 的指针赋值给此类时会调用此函数
//使用方法:使用赋值操作符赋值
//使用注意:用户将一个类型为 T * 的动态内存分配得到的指针 lptTPtr 赋值给
// 此类后,不要寄希望于此类能够自动释放其内存:此类不会去释放
// lptTPtr 指向的内存,因为 lptTPtr 的来源也有可能不是动态内存分
// 配的结果。
// 例如:T t ;
// T * lptTPtr = & t ;
// 如果此类尝试去释放 lptTPtr 指向的内存则必然会引起错误。
//附带说明:用户将 lptTPtr 赋值给此类后应该自己负责 lptTPtr 指向的内存释放
//---------------------------------------------------------------------------------------------
JCreateInst & operator =( T * lptTPtr )
{
//只是更改此类的 this->m_lptInstPtr 变量
this->m_lptInstPtr = lptTPtr ;
return * this ;
}
} ;
#endif
如果您修改了一个代码片段并且觉得很应该让别人共享,您可以把这作为这个代码片段的最新版本提交上来. |
|