C++的构造函数与内存分配设计

作者:张维,引用请注明来源



设计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;
}










 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值