您的位置:首页 > 编程语言 > C语言/C++

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

2013-12-03 11:53 337 查看
作者:张维,引用请注明来源

设计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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: