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

原创 2013年12月03日 11:53:25

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



设计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++类的构造函数与析构函数

C++中每个类都有其构造与析构函数,它们负责对象的创建和对象的清理和回收,即使我们不写这两个,编译器也会默认为我们提供这些构造函数。下面仍然是通过反汇编的方式来说明C++中构造和析构函数是如何工作的。...
  • lanuage
  • lanuage
  • 2016年06月29日 22:11
  • 3133

c++构造函数和析构函数的区别?

构造函数: 什么是构造函数?通俗的讲,在类中,函数名和类名相同的函数称为构造函数。它的作用是在建立一个对象时,作某些初始化的工作(例如对数据赋予初值)。C++允许同名函数,也就允许在一个类中有多个构...
  • xinsong520
  • xinsong520
  • 2016年08月25日 18:35
  • 556

构造函数和this指针浅谈

什么是构造函数 类通过一个或者多个特殊的成员函数来控制其对象的初始化过程,其任务是初始化类对象的数据成员。 构造函数的一些特性: 1.      无论何时只要类的对象被创建,编译器就自动调用构造函数,...
  • xy913741894
  • xy913741894
  • 2016年09月26日 23:20
  • 842

深入java (类)构造函数和对象创建的内存分配

之前的文章总结了java一些较为常用的关键字,现在我们要进入到类里面,总结类的特征(其中包括了内存和构造函数,gc垃圾回收),java中类的继承和初始化顺序(会涉及到ClassLoader),java...
  • yabay2208
  • yabay2208
  • 2017年05月11日 17:44
  • 618

C++中构造函数的作用

构造函数用于解决类中的对象初始化的问题 构造函数是一类特殊的函数,与其他的成员函数不同的是构造函数构造函数不需要用户来调用它,而是建立对象的时候自动的执行#include //#include "...
  • andrewgithub
  • andrewgithub
  • 2017年03月02日 15:30
  • 1917

C++构造函数和析构函数的总结

C++是面向对象的编程语言,在定义类的时候,离不开构造和析构函数。类中同类同名的成员函数称为构造函数,主函数中初始化一个对象时,如果有传入数据,其实是传入到构造函数的形参中。...
  • ladybai
  • ladybai
  • 2016年03月10日 14:51
  • 3194

C++构造函数与析构函数的解析

创建一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。 注意,类的数据成员是不能在声明类时初始化的。如果一个类中所有的成员都是公用的,则可以在定义对象时对数据成员进行初始化。如: ...
  • u011392772
  • u011392772
  • 2015年01月16日 09:20
  • 7605

对C++中构造函数、析构函数、虚函数及普通成员函数的理解

这里我们主要讨论构造函数、析构函数、普通成员函数、虚函数,对这几种函数说说自己的理解。 对构造函数的总结 对构造函数,我们先来看看如下的代码 #include using namespac...
  • Veaxen
  • Veaxen
  • 2017年04月08日 01:26
  • 674

c/c++中内存分配

在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的。因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题。 第1节主要介绍内存管理基本概念,...
  • msdnwolaile
  • msdnwolaile
  • 2016年02月21日 17:30
  • 907

深入理解C++类的构造函数与析构函数

在研究C++类的继承、派生、组合时,一直没有清晰地了解构造函数与析构函数的调用过程。本章通过点-线组合类,来深入分析组合类情况下,对象的构造与析构。 1.问题的引入 源代码: #include ...
  • shenziheng1
  • shenziheng1
  • 2016年07月13日 23:16
  • 1921
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++的构造函数与内存分配设计
举报原因:
原因补充:

(最多只允许输入30个字)