作者:张维,引用请注明来源
设计C++类的时候
最好自己实现两个成员方法
Construct,Destruct
用在构造函数和析构函数
再写一个Init相关的方法,用来分配空间等操作,
构造函数一般不要分配内存空间,只用来初始化各个变量,以防违法操作,如置0之类
如果构造函数分配了空间,那在实现copy constructor的时候会浪费空间
如果一定要分配空间,那,最好分两步
一步是变量初始化,一步是空间分配
在copy constructor中,调用一次Construct,
在operator=中,调用一次Destruct
一度想给每个类设计一个Init方法
用在constructor之后让用户自己调用
但还是觉得内存要按需分配
如,在Array中,等Set方法被调用的时候再检查内存
#ifndef h_EtArrSz
#define h_EtArrSz
#include "et_base_include.h"
#define ET_ARR_SZ_SECTION_COUNT 1000
#define ET_ARR_SZ_DEFAULT_SECTION_SIZE 10
#define ET_ARR_SZ_DEFAULT_NODE_SIZE 4000
#define ET_ARR_SZ_TRAIL_SIZE 2
namespace et{
class EtArrSz{
public:
EtArrSz();
EtArrSz(INT64 iInitNodeCount, INT64 iStrSize);
~EtArrSz();
EtArrSz(const EtArrSz& rCopy);
EtArrSz& operator = (const EtArrSz& rCopy);
INT64 Set(INT64 iIndex, const char* szValue);
char* Get(INT64 iIndex) const;
void Clear();
INT64 Size() const;
INT64 Capacity() const;
bool Exist(const char* szValue) const;
INT64 Find(const char* szValue) const;
INT64 GetInitNodeCount() const;
INT64 GetNodeSize() const;
char** GetArrBuf() const;
INT64* GetSectionSizeTable() const;
private:
char* m_arrBuf[ET_ARR_SZ_SECTION_COUNT];
INT64 m_arrSectionSizeTable[ET_ARR_SZ_SECTION_COUNT];
INT64 m_iNodeSize;
INT64 m_iCapacity;
INT64 m_iMaxNodeIndex;
INT64 m_iMaxSectionIndex;
INT64 m_iInitNodeCount;
void Construct(INT64 iInitNodeCount, INT64 iStrSize);
void Destruct();
void CopyToThis(const EtArrSz& rCopy);
INT64 FindPosition(INT64 iIndex, INT64* piSection, INT64* piOffset) const;
char* FindBuf(INT64 iSection, INT64 iOffset) const;
bool HasEnoughSpace(INT64 iIndex) const;
INT64 CheckSpace(INT64 iIndex);
INT64 ComputeNewSectionSize(INT64 iNewIndex) const;
INT64 Grow(INT64 iNewSectionSize);
};//EtArrSz
}//end et
实现
#include "EtArrSz.h"
#include <iostream>
using namespace std;
et::EtArrSz::EtArrSz()
{
this->Construct(ET_ARR_SZ_DEFAULT_SECTION_SIZE, ET_ARR_SZ_DEFAULT_NODE_SIZE);
}
et::EtArrSz::EtArrSz(INT64 iInitNodeCount, INT64 iStrSize){
this->Construct(iInitNodeCount, iStrSize);
}
et::EtArrSz::EtArrSz(const EtArrSz& rCopy)
{
this->Construct(ET_ARR_SZ_DEFAULT_SECTION_SIZE, ET_ARR_SZ_DEFAULT_NODE_SIZE);
this->CopyToThis(rCopy);
}
EtArrSz& et::EtArrSz::operator=(const EtArrSz& rCopy)
{
this->Destruct();
this->CopyToThis(rCopy);
return *this;
}
et::EtArrSz::~EtArrSz(){
this->Destruct();
}
void et::EtArrSz::Construct(INT64 iInitNodeCount, INT64 iStrSize)
{
INT64 i = 0;
if (iInitNodeCount <= 0){
iInitNodeCount = ET_ARR_SZ_DEFAULT_SECTION_SIZE;
}
this->m_iInitNodeCount = iInitNodeCount;
if (iStrSize <= 0){
iStrSize = ET_ARR_SZ_DEFAULT_NODE_SIZE;
}
this->m_iNodeSize = iStrSize;
this->m_iCapacity = 0;
this->m_iMaxNodeIndex = -1;
this->m_iMaxSectionIndex = -1;
for (i = 0; i < ET_ARR_SZ_SECTION_COUNT; i++){
this->m_arrBuf[i] = null;
this->m_arrSectionSizeTable[i] = 0;
}
}
void et::EtArrSz::Destruct()
{
INT64 i = 0;
if (this->m_iCapacity == 0){
return;
}
for (i = 0; i < ET_ARR_SZ_SECTION_COUNT; i++){
ET_FREE(this->m_arrBuf[i]);
this->m_arrBuf[i] = null;
this->m_arrSectionSizeTable[i] = 0;
}
this->m_iCapacity = 0;
this->m_iMaxNodeIndex = -1;
this->m_iMaxSectionIndex = -1;
this->m_iInitNodeCount = 0;
this->m_iNodeSize = 0;
}
INT64 et::EtArrSz::Init()
{
return 0;
}
void et::EtArrSz::CopyToThis(const EtArrSz& rCopy)
{
INT64 i = 0;
char** pArrBuf = null;
INT64* pSecTable = null;
INT64 iTempSize = 0;
pArrBuf = rCopy.GetArrBuf();
pSecTable = rCopy.GetSectionSizeTable();
this->m_iCapacity = rCopy.Capacity();
this->m_iMaxNodeIndex = rCopy.Size() - 1;
for (i = 0; i < ET_ARR_SZ_SECTION_COUNT; i++){
if (pSecTable[i] == 0){
this->m_iMaxSectionIndex = i - 1;
break;
}
this->m_arrSectionSizeTable[i] = pSecTable[i];
iTempSize = this->m_arrSectionSizeTable[i] * (this->m_iNodeSize + ET_ARR_SZ_TRAIL_SIZE);
this->m_arrBuf[i] = (char*)ET_ALLOC(iTempSize);
et_memcpy(this->m_arrBuf[i], pArrBuf[i], iTempSize);
this->m_arrBuf[i][0] = 0;
}
}
void et::EtArrSz::Clear(){
INT64 i = 0;
for (i = 0; i < this->m_iMaxSectionIndex; i++){
if (i > 0){
ET_FREE(this->m_arrBuf[i]);
this->m_arrBuf[i] = null;
this->m_arrSectionSizeTable[i] = 0;
}
}
if (this->m_iCapacity > 0){
this->m_arrBuf[0][0] = 0;
this->m_iCapacity = m_iInitNodeCount;
this->m_iMaxNodeIndex = -1;
this->m_iMaxSectionIndex = 0;
}
}
INT64 et::EtArrSz::Grow(INT64 iNewSectionSize){
INT64 iDiff = 0;
if(iNewSectionSize <= 0){
return iNewSectionSize;
}
this->m_iMaxSectionIndex++;
this->m_arrSectionSizeTable[this->m_iMaxSectionIndex] = iNewSectionSize;
this->m_arrBuf[this->m_iMaxSectionIndex] = (char*)ET_ALLOC(iNewSectionSize * (this->m_iNodeSize + ET_ARR_SZ_TRAIL_SIZE));
this->m_arrBuf[this->m_iMaxSectionIndex][0] = 0;
//et_memset(this->m_arrBuf[this->m_iMaxSectionIndex],0,iNewSectionSize * (this->m_iNodeSize + 2));
this->m_iCapacity += iNewSectionSize;
return 0;
}
INT64 et::EtArrSz::Size() const{
return this->m_iMaxNodeIndex +1;
}
bool et::EtArrSz::HasEnoughSpace(INT64 iIndex) const{
if(this->m_iCapacity > iIndex){
return true;
}
return false;
}
INT64 et::EtArrSz::FindPosition(INT64 iIndex, INT64* piSection, INT64* piOffset) const{
INT64 i = 0;
INT64 iBase = 0;
INT64 iSection = -1;
if(this->m_iCapacity <= iIndex){
return -1;
}
for(i = 0; i < this->m_iMaxSectionIndex; i++){
if(iBase + this->m_arrSectionSizeTable[i] > iIndex){
iSection = i;
break;
}
iBase += this->m_arrSectionSizeTable[i];
}
if(iSection < 0){
return iSection;
}
*piSection = iSection;
*piOffset = iIndex - iBase;
return 0;
}
char* et::EtArrSz::FindBuf(INT64 iSection, INT64 iOffset) const{
return this->m_arrBuf[iSection] + iOffset * (this->m_iNodeSize + ET_ARR_SZ_TRAIL_SIZE);
}
INT64 et::EtArrSz::ComputeNewSectionSize(INT64 iNewIndex) const{
INT64 iDiff = 0;
INT64 iNewSectionSize = 0;
if(this->m_iCapacity > iNewIndex){
return 0;
}
iDiff = iNewIndex + 1 - this->m_iCapacity;
if(this->m_iInitNodeCount >= iDiff){
iNewSectionSize = this->m_iInitNodeCount;
}else{
iNewSectionSize = iDiff + this->m_iInitNodeCount;
}
return iNewSectionSize;
}
char* et::EtArrSz::Get(INT64 iIndex) const{
INT64 iSection = 0;
INT64 iOffset = 0;
INT64 iRet = 0;
if(this->m_iMaxNodeIndex < iIndex){
return null;
}
iRet = this->FindPosition(iIndex,&iSection,&iOffset);
if(iRet < 0){
return null;
}
return this->FindBuf(iSection,iOffset);
}
INT64 et::EtArrSz::Set(INT64 iIndex, const char* szValue){
INT64 iSection = 0;
INT64 iOffset = 0;
INT64 iRet = 0;
char* pBuf = null;
if(szValue == null){
return 0;
}
iRet = this->CheckSpace(iIndex);
if(iRet < 0){
return iRet;
}
iRet = this->FindPosition(iIndex,&iSection,&iOffset);
if(iRet < 0){
return iRet;
}
pBuf = this->FindBuf(iSection,iOffset);
if(pBuf == null){
return -1;
}
et_strncpy(pBuf,szValue,this->m_iNodeSize);
if(this->m_iMaxNodeIndex < iIndex){
this->m_iMaxNodeIndex = iIndex;
}
return 0;
}
INT64 et::EtArrSz::CheckSpace(INT64 iIndex){
INT64 iRet = 0;
INT64 iNewSectionSize = 0;
if(this->HasEnoughSpace(iIndex)){
return 0;
}
iNewSectionSize = this->ComputeNewSectionSize(iIndex);
if(iNewSectionSize < 0){
return iNewSectionSize;
}
iRet = this->Grow(iNewSectionSize);
return iRet;
}
INT64 et::EtArrSz::Capacity() const{
return this->m_iCapacity;
}
bool et::EtArrSz::Exist(const char* szValue) const{
return (this->Find(szValue) >= 0);
}
INT64 et::EtArrSz::Find(const char* szValue) const{
INT64 i = 0;
INT64 j = 0;
INT64 iIndexCount = 0;
INT64 iSecSize = 0;
INT64 iSrcLen = 0;
char* pSecBuf = null;
char* pNodePos = null;
if (szValue == null){
return -1;
}
iSrcLen = et_strlen(szValue);
if (iSrcLen > m_iNodeSize){
return -1;
}
for (i = 0; i < ET_ARR_SZ_SECTION_COUNT; i++){
iSecSize = this->m_arrSectionSizeTable[i];
pSecBuf = m_arrBuf[i];
for (j = 0; j < iSecSize; j++){
pNodePos = pSecBuf + j * (m_iNodeSize + ET_ARR_SZ_TRAIL_SIZE);
if (et_strncmp(pNodePos, szValue, iSrcLen) == 0 && *(pNodePos + iSrcLen) == 0){
return iIndexCount;
}
if (iIndexCount >= m_iMaxNodeIndex){
break;
}
iIndexCount++;
}
if (i >= this->m_iMaxSectionIndex){
break;
}
}
return -1;
}
INT64 et::EtArrSz::GetInitNodeCount() const
{
return this->m_iInitNodeCount;
}
INT64 et::EtArrSz::GetNodeSize() const
{
return this->m_iNodeSize;
}
char** et::EtArrSz::GetArrBuf() const
{
return (char**)this->m_arrBuf;
}
INT64* et::EtArrSz::GetSectionSizeTable() const
{
return (INT64*)this->m_arrSectionSizeTable;
}