初始化与清除

来源:互联网 发布:java在线教学系统源码 编辑:程序博客网 时间:2024/06/04 18:24

在对象定义的地方,编译器会插入对象的构造函数;在对象销毁的地方,编译器会插入对象的析构函数。传递给这两个函数的的第一个参数就是当前对象的this指针(隐藏起来了)。所以定义一个对象时,会先分配一块内存块,然后把这个内存块的基址传给构造函数,构造函数负责对这个内存块进行初始化。而在销毁一个对象之前,先把这个对象的基址传给析构函数,析构函数对这个内存块进行清理收尾的工作,然后才销毁这个对象(如出栈,逻辑上销毁了这个对象,但在物理内存中这个对象占用的空间还是存在的。把不再使用的空间置零是一个好的习惯。)。
不调用构造函数是无法真正完成构造一个对象的,不调用析构函数是无法销毁一个对象的(longjmp另作考虑),因为C++编译器做了手脚。比如:
class  X
{
public:
 X() {}
};
void func( int  i )
{
 if ( i < 10 )
 {
  goto  lable1;
 }
}
X  obj1;  // 这里可能被跳过,而在编译时这里就给分配了内存块,而现在这个内存块可能没被初始化(构造函数的定义就放在X obj1语句的后面,而它可能被跳过),所以对这样的写法,编译器会给出出错信息。

lable1:
 ....


同样对于这样的写法也是报错的:
switch( int n )
{
 case 1:
  X  obj2;  // 编译时就分配了空间,但可能构造函数给跳过而没有初始化,所以报错
  break;
 case 2:
  X  obj3;  // 报错
  break;
 ...


顺序数组的一个实现(可用作缓存):
/***
* 直接存储对象的数组 头文件
* bluesky
*/

#ifndef _DIRECTARRAY_H_
#define _DIRECTARRAY_H_

#include <cstdlib>
#include <string.h>

namespace  _bs_classes_
{
 const int  INC_COUNT = 100;

 class DirectArray
 {
 public:
  DirectArray( int  nElementSize );
  virtual ~DirectArray( );

 public:
  // 增加一个元素
  // 成功则返回这个元素的下标,否则返回-1
  int  AddElement( void * pNewElement );

  // 取一个元素
  // 成功则返回这个元素的地址,否则返回0
  void * FetchElement( int  nIndex );

  // 取得数组元素的个数
  int  GetCount( );

  // []操作
  void *  operator[]( int nIndex );
 private:
  // 增长数组
  bool InflateArray( int  nIncElementCount );

 private:
  int  m_nElementSize;  // 元素占用的字节数
  int  m_nCurrentQuantity;  // 当前能容纳的元素个数
  int  m_nNextElementIndex; // 最后一个元素的下一个位置的下标
  unsigned char *  m_pArrayStartAddr; // 数组起始地址  
 };
}

#endif

/***
* 直接存储数组 实现文件
* bluesky
*/

#include "DirectArray.h"
#include <cassert>

namespace  _bs_classes_
{
 DirectArray::DirectArray( int nElementSize )
 {
  m_pArrayStartAddr = 0;

  assert( nElementSize > 0 );
  if ( nElementSize <= 0 )
   return;

  m_nElementSize = nElementSize;
  m_nCurrentQuantity = 0;
  m_nNextElementIndex = 0;
 }

 DirectArray::~DirectArray( )
 {
  if ( m_pArrayStartAddr )
  {
   free( m_pArrayStartAddr );
   m_pArrayStartAddr = 0;
  }
 }

 ///////////////////// 对外接口 begin

 int  DirectArray::AddElement( void * pNewElement )
 {
  assert( pNewElement );
  if ( !pNewElement )
   return  -1;

  if ( m_nNextElementIndex >= m_nCurrentQuantity )
  {
   bool bIsInflateSuccessful = InflateArray( INC_COUNT );
   if ( !bIsInflateSuccessful )
    return    -1;
  }

  memcpy( m_pArrayStartAddr + m_nNextElementIndex * m_nElementSize, pNewElement, m_nElementSize );
  m_nNextElementIndex ++;

  return m_nNextElementIndex - 1;
 }

 void * DirectArray::FetchElement( int nIndex )
 {
  assert( nIndex >= 0 && nIndex < m_nNextElementIndex );
  if ( nIndex < 0 || nIndex >= m_nNextElementIndex )
   return 0;

  return m_pArrayStartAddr + nIndex * m_nElementSize;

 }

 void *  DirectArray::operator[]( int nIndex )
 {
  return FetchElement( nIndex );
 }

 int  DirectArray::GetCount( )
 {
  return  m_nNextElementIndex;
 }

 ///////////////////// 对外接口 end

 //////////////// 内部函数 begin
 bool DirectArray::InflateArray( int nIncElementCount )
 {
  assert( nIncElementCount > 0 );
  if ( nIncElementCount <= 0 )
   return false;

  void *  pNewMemoryStartAddr = (void *)realloc( m_pArrayStartAddr,
   ( m_nCurrentQuantity + nIncElementCount ) * m_nElementSize );
  assert ( pNewMemoryStartAddr );
  if ( pNewMemoryStartAddr == 0 )
   return false;

  m_pArrayStartAddr = (unsigned char *)pNewMemoryStartAddr;
  m_nCurrentQuantity += nIncElementCount;

  return true;
 }
 //////////////// 内部函数 end
}


/* 测试代码
*  bs
*/

#include <iostream>
using namespace std;

#include "DirectArray.h"
using namespace _bs_classes_;

void testDirectArray( )
{
 DirectArray  intArray( sizeof(int) );
 int  aa = 10;
 intArray.AddElement( &aa );
 aa = 20;
 intArray.AddElement( &aa );
 int  nSize = intArray.GetCount( );
 for ( int nPos = 0; nPos < nSize; nPos ++ )
 {
  cout << *((int*)intArray[nPos]) << endl;
 }
 

 // 用作缓存

 const  int BUFFER_SIZE = 128;
 char  szBuffer[ BUFFER_SIZE ] = { 0 };
 DirectArray  stringStash( sizeof(char) * BUFFER_SIZE );  // 一个元素占BUFFER_SIZE个字节
 
 FILE * pFile = fopen( "DirectArray.cpp", "r" );
 if ( pFile != NULL )
 {
  while ( fgets( szBuffer, BUFFER_SIZE - 1, pFile ) )
  {
   stringStash.AddElement( (void*)szBuffer );
  }
 }
 
 // print string in stringStash
 for ( int nIndex = 0; nIndex < stringStash.GetCount(); nIndex ++ )
 {
  cout << (char *)stringStash[ nIndex ] << endl;
 }

}

 

链式栈的一个实现(单链表实际上就可以作为栈,而不是让栈包含一个单链表):
/************************************************************************/
/* 栈 声明文件
/* bluesky
/************************************************************************/

#ifndef  _BS_STACK_H
#define  _BS_STACK_H

namespace _bs_stack
{
 class Stack
 {
 private:
  struct Element
  {
   void *  m_pData;  // point to real data
   Element * m_pNext; // next pointer
   void Initialize( void * pData, Element * pElement );
   Element( void * pData, Element * pElement );
  } *head;

  int  m_nSize;  // element amount of stack
  void (*m_pDestroy)( void * pData );  // 销毁实际数据的指针函数

 public:
   // 由于本结构是不考虑实际数据的类型和它的产生方式的,所以要记录下外界对实际数据的销毁函数的指针
   // param destroy  销毁实际数据的指针函数
  Stack(
   void (*destroy)(void * pData)
   );

  ~Stack( );
  void ZeroInit( );

 public:
  void push( void * pData );
  void * pop( );
  void *  peek( );
  int size( ) { return m_nSize; }
 };
}

#endif  // _BS_STACK_H

/************************************************************************/
/* 栈 实现文件
/* bluesky
/************************************************************************/

#include "Stack.h"
using  namespace _bs_stack;

#include <cassert>
#include <cstring>
#include <cstdlib>

void Stack::ZeroInit( )
{
 head = 0;
 m_nSize = 0;
 m_pDestroy = 0;
}

Stack::Stack(
    void (*destroy)(void * pData)
    )
{
 ZeroInit();

 m_pDestroy = destroy;
}

Stack::~Stack( )
{
 if ( m_nSize == 0 )
 {
  memset( (void*)this, 0, sizeof(Stack) );
  return;
 }

 Element * pElementTemp = head;
 while ( head )
 {
  pElementTemp = head->m_pNext;
 
  void * pData = head->m_pData;
  //free( pData );   // 不能一概用free,有可能是new出来的,由外界的接口来销毁是最合适的
  m_pDestroy( pData );
  free( head );

  head = pElementTemp;
 }

 memset( (void*)this, 0, sizeof(Stack) );
}

////////////////////////////////////////////////////////////////////////// 对外接口 begin

void Stack::push(
     void * pData
     )
{
 assert( pData != 0 );
 if ( pData ==  0 )
  return;

 Element * pNewElement = (Element *)malloc( sizeof(Element) ); 
 assert( pNewElement );
 pNewElement->Initialize( pData, head );
 head = pNewElement;

 m_nSize ++;
}

void * Stack::pop( )
{
 if ( m_nSize == 0 )
  return 0;

 Element * pElementTemp = head;
 head = head->m_pNext;

 void * pRetData = pElementTemp->m_pData;
 
 free( pElementTemp );
 m_nSize --;

 return pRetData;  // 外界负责管理这个内存块
}

void * Stack::peek()
{
 if ( m_nSize == 0 )
  return 0;

 return head->m_pData;
}

////////////////////////////////////////////////////////////////////////// 对外接口 end

////////////////////////////////////////////////////////////////////////// 内部结构 begin

Stack::Element::Element(
      void * pData,
      Element * pElement
      )
{
 m_pData = pData;
 m_pNext = pElement;
}

void Stack::Element::Initialize(
           void * pData,
           Element * pElement
           )
{
 m_pData = pData;
 m_pNext = pElement;
}

////////////////////////////////////////////////////////////////////////// 内部结构 end

/* 测试代码
*  bluesky
*/
#include <iostream>
using namespace std;

#include <string>
#include <cstdlib>
#include <cassert>

#include "Stack.h"
using  namespace _bs_stack;

void destroy( void * pData )
{
 assert( pData );
 if ( !pData )
  return;

 delete pData;
 pData = 0;
}

void testStack1( )
{
 Stack  intStack( destroy );
 
 int   nPos = 0;
 const int nLen = 10;
 for ( nPos = 0; nPos < nLen; nPos ++ )
 {
  intStack.push( (void*)new int(nPos) );
 }

 int * pInt = 0;
 while ( pInt = (int*)intStack.pop() )
 {
  cout << *pInt << endl;
  delete pInt;
 }

 cout << "now stack size: " << intStack.size() << endl;
}

void destroy2( void * pData )
{
 assert( pData );
 if ( !pData )
 {
  return;
 }

 free( pData );
 pData = 0;
}

void testStack2( )
{
 Stack  txtStack( destroy2 );

 FILE * pFile = fopen( "Stack.h", "r" );
 assert( pFile );
 if ( !pFile )
 {
  cout << "open file error" << endl;
  return;
 }

 const int  bufferSize = 126;
 char  buf[ bufferSize ] = { 0 };
 while ( fgets( buf, bufferSize, pFile ) )
 {
  void * pData = malloc( strlen( buf ) + 1 );
  memset( pData, 0, strlen( buf ) + 1 );

  strcpy( (char*)pData, buf );

  txtStack.push( pData );
 }

 cout << "now stack size before pop: " << txtStack.size( ) << endl;

 int nTimesLimit = 30;
 void  * pRealData = 0;
 int   nTimes = 0;
 while ( pRealData = txtStack.pop() )
 {
  cout << (char*)pRealData << endl;
  free( pRealData );
  pRealData = 0;

  nTimes ++;
  if ( nTimes > nTimesLimit )
   break;
 }

 cout << "now stack size: " << txtStack.size( ) << endl;
}

void  destroy3( void * pData )
{

}

void testStack3( )
{
 Stack  intStack( destroy3 );
 int  intArray[ 5 ] = {1, 2, 3, 4, 5};
 int  nPos = 0;
 for ( nPos = 0; nPos < 5; nPos ++ )
 {
  intStack.push( &intArray[nPos] );
 }

 cout << "stack size before pop: " << intStack.size() << endl;

 int nTimesLimit = 2;
 int nTimes = 0;
 void * pData = 0;
 while ( pData = intStack.pop() )
 {
  cout << *(int*)pData << endl;

  nTimes ++;
  if ( nTimes > nTimesLimit )
   break;
 }

 cout << "stack size after pop: " << intStack.size() << endl;
}

 

集合初始化的几个例子:
int a[10] = {0}; //每个初化为0
struct AA
{
 int aa;
 float bb;
};
AA  sA = {14, 1.0f};  //直接初始化

int  a[] = {12, 13, 90};
则元素的个数为: sizeof a / sizeof *a

 

原创粉丝点击