C++的构造函数与内存分配设计
2013-12-03 11:53
337 查看
作者:张维,引用请注明来源
设计C++类的时候
最好自己实现两个成员方法
Construct,Destruct
用在构造函数和析构函数
再写一个Init相关的方法,用来分配空间等操作,
构造函数一般不要分配内存空间,只用来初始化各个变量,以防违法操作,如置0之类
如果构造函数分配了空间,那在实现copy constructor的时候会浪费空间
如果一定要分配空间,那,最好分两步
一步是变量初始化,一步是空间分配
在copy constructor中,调用一次Construct,
在operator=中,调用一次Destruct
一度想给每个类设计一个Init方法
用在constructor之后让用户自己调用
但还是觉得内存要按需分配
如,在Array中,等Set方法被调用的时候再检查内存
实现
设计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; }
相关文章推荐
- 网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- 【小记备忘】之C/C++ 杂记,catch,调用构造函数,内存分配,隐式转换【2013.12.11】
- 网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- 网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- [C++] 分别设计只能在栈, 堆中分配内存的类!
- C++:动态内存分配和释放、类型转换、面向对象编程、构造函数
- 网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- C++[类设计] 一个使用new动态内存分配的集合类
- [C++] 分别设计只能在栈, 堆中分配内存的类!
- 网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- c++ 使用动态内存分配的类需要显式复制构造函数,赋值构造函数,析构函数
- C++动态内存分配---两级allocator设计与实现(二)
- (转载)网易校园招聘c++题目--如何让new操作符不分配内存,只调用构造函数
- C++内存分配的五种方法 与 c++内存问题
- C/C++ struct初始化/复制/内存分配技巧
- 从一个微型例子看“C/C++的内存分配机制”和“数组变量名与指针变量名”
- c和c++中的内存分配和内存释放函数
- C/C++ 中 内存的动态分配 ------很基础但很有用
- 如何让new 操作 不分配内存 只调用构造函数
- C++内存分配方式详解