new-delete_Vector

目录

1.malloc与new

1.malloc函数

2.new关键字

3.free函数

4.delete关键字

5.new和delete关键字用法

析构函数何时被调用

2.Vector

         什么是Vector?

3.作业 


1.malloc与new

我们使用一个malloc函数,进入到反汇编查看代码

1.malloc函数

2.new关键字

3.free函数

4.delete关键字

5.new和delete关键字用法

我们发现malloc和new调用的函数到最后都是同一个系统函数,new调用了库函数malloc,编译器替我们实现了某一下功能。

假如,我们想在堆中分配1024个字节的空间,那么我们可以通过malloc实现

那如果我们想在堆中分配一个int、char、struct类型的空间呢

这里就可以用到new了,new关键字让编译器替我们实现这一功能。

#include<stdio.h>
int main()
{

	int* pi=new int;//分配1个四字节的空间
	delete pi;

	int* pi=new int(5);//分配1个四字节空间并赋值为5
	delete pi;

	int* pi=new int[5];//分配4个四字节空间
	delete[5] pi;

    Base* pi=new Base;//分配1个类字节的空间
	delete pi;

	Base* pi=new Base[3];//分配3个类字节的空间
	delete[3] pi;

    Base* pi=new Base(1,2);//分配1个类的空间,构造函数传参1,2
    delete pi;

	return 0;
}


通过析构函数来判断是否释放空间

#include<stdio.h>
#include<stdlib.h>

class Base
{
	int x;
	int y;
public:
	Base(int x,int y)
	{
		this->x=x;
		this->y=y;
	}
	~Base()
	{
		printf("delete Base\n");//析构函数
	}
	void Print()
	{
		printf("%d  %d\n",x,y);
	}
};
int main()
{

	Base* pi=new Base(1,2);
	pi->Print();
	delete pi;

	return 0;
}

析构函数何时被调用

析构函数是在对象消亡时,自动被调用,用来释放对象占用的空间。

有四种方式会调用析构函数:

  • 1.生命周期:对象生命周期结束,会调用析构函数。

  • 2.delete:调用delete,会删除指针类对象。

  • 3.包含关系:对象Dog是对象Person的成员,Person的析构函数被调用时,对象Dog的析构函数也被调用。

  • 4.继承关系:当Person是Student的父类,调用Student的析构函数,会调用Person的析构函数。

2.Vector

什么是Vector?

个人认为vector其实更像一个“遥控器”,它具有很多功能,我们根据自己的需求去“按按钮”

  1. vector是表示可变大小数组的序列容器。
  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  6. 与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。

3.作业 

写一个Vector,实现增删查改等功能

#include<stdio.h>
#include<Windows.h>


#define m_SUCCESS 1 // 成功								
#define m_ERROR -1 // 失败								
#define m_MALLOC_ERROR -2 // 申请内存失败								
#define m_INDEX_ERROR -3 // 错误的索引号								
											
											
template <class T_ELE>											
class Vector											
{											
public:											
	Vector();										
	Vector(DWORD dwSize);										
	~Vector();										
public:											
	DWORD	at(DWORD dwIndex,OUT T_ELE* pEle);					//根据给定的索引得到元素				
    DWORD   push_back(T_ELE Element);						//将元素存储到容器最后一个位置				
	VOID	pop_back();					//删除最后一个元素				
	DWORD	insert(DWORD dwIndex, T_ELE Element);					//向指定位置新增一个元素				
	DWORD	capacity();					//返回在不增容的情况下,还能存储多少元素				
	VOID	clear();					//清空所有元素				
	BOOL	empty();					//判断Vector是否为空 返回true时为空				
	DWORD	erase(DWORD dwIndex);					//删除指定元素				
	DWORD	size();					//返回Vector元素数量的大小				
private:											
	BOOL	expand();									
private:											
	DWORD  m_dwIndex;						//下一个可用索引				
	DWORD  m_dwIncrement;						//每次增容的大小				
	DWORD  m_dwLen;						//当前容器的长度				
	DWORD  m_dwInitSize;						//默认初始化大小				
	T_ELE *m_pVector;						//容器指针				
};															
							
template <class T_ELE>											
Vector<T_ELE>::Vector()				//无参数的构造函数							
:m_dwInitSize(4),m_dwIncrement(5)											
{											
	//1.创建长度为m_dwInitSize个T_ELE对象										
	m_pVector=new T_ELE[m_dwInitSize];									
	//2.将新创建的空间初始化										
	memset(m_pVector,0,sizeof(T_ELE)*m_dwInitSize);								
	//3.设置其他值	
	m_dwIndex=0;
	m_dwLen=m_dwInitSize;				
}	
										
template <class T_ELE>				//有参数的构造函数							
Vector<T_ELE>::Vector(DWORD dwSize)	
:m_dwIncrement(5)											
{											
	//1.创建长度为dwSize个T_ELE对象										
	m_pVector=new T_ELE[dwSize];											
	//2.将新创建的空间初始化																
	memset(m_pVector,0,sizeof(T_ELE)*dwSize);											
	//3.设置其他值	
	m_dwIndex=0;
	m_dwLen=dwSize;

}

template <class T_ELE>					//释放空间						
Vector<T_ELE>::~Vector()											
{											
											
	//释放空间 delete[]
	delete [] m_pVector;
	m_pVector=NULL;
											
}											
											
template <class T_ELE>											
BOOL Vector<T_ELE>::expand()			//进行扩容								
{											
	// 1. 计算增加后的长度										
	DWORD tmp_Size=m_dwLen+m_dwIncrement;										
		
	// 2. 申请空间										
	T_ELE* tmp_pVector = new T_ELE[tmp_Size];										
	memset(tmp_pVector,0,tmp_Size*sizeof(T_ELE));//初始化空间										
	// 3. 将数据复制到新的空间										
	memcpy(tmp_pVector,m_pVector,m_dwLen*sizeof(T_ELE));										
											
	// 4. 释放原来空间										
	delete[] m_pVector;										
	m_pVector=tmp_pVector;
	tmp_pVector=NULL;
	// 5. 为各种属性赋值
	m_dwLen=tmp_Size;     //此时不修改Index是因为在其他插入函数中有了对于长度属性的修改

	return m_SUCCESS;
											
}											
											
template <class T_ELE>											
DWORD Vector<T_ELE>::push_back(T_ELE Element)		//写入函数,如果空间里一个没存,就存在第一个     如果存了,就接着存								
{											
	//1.判断是否需要增容,如果需要就调用增容的函数										
	if(m_dwIndex>=m_dwLen)
	{
		expand();
	}
	//2.将新的元素复制到容器的最后一个位置										
	memcpy(&m_pVector[m_dwIndex],&Element,sizeof(T_ELE));										
	//3.修改属性值										
	m_dwIndex++;    //此时不修改长度属性是因为,再增容函数中已经有了对于长度属性的修改
	
	return m_SUCCESS;
}											
											
template <class T_ELE>											
DWORD  Vector<T_ELE>::insert(DWORD dwIndex, T_ELE Element)		//插入函数							
{	
	//1.判断索引是否在合理区间										
	if(dwIndex>m_dwLen || dwIndex<0)
	{
		return m_INDEX_ERROR;
	}
													
	//2.判断是否需要增容,如果需要就调用增容的函数										
	if(m_dwIndex>=m_dwLen)
	{
		expand();
	}
	// 0 1 2 3 4 5 6 7														
	//3.将dwIndex之后的元素后移										
	for(int i=m_dwIndex;i>dwIndex;i--)
	{
		memcpy(&m_pVector[i],&m_pVector[i-1],sizeof(T_ELE));
	}
											
	//4.将Element元素复制到dwIndex位置										
	memcpy(&m_pVector[dwIndex],&Element,sizeof(T_ELE));										
											
	//5.修改属性值		
	m_dwIndex++;

	return m_SUCCESS;
}
											
template <class T_ELE>											
DWORD Vector<T_ELE>::at(DWORD dwIndex,T_ELE* pEle)											
{											
	//判断索引是否在合理区间										
	if(dwIndex>=m_dwIndex)
	{
		return m_INDEX_ERROR;
	}
											
	//将dwIndex的值复制到pEle指定的内存	
	memcpy(pEle,&m_pVector[dwIndex],sizeof(T_ELE));

	return m_SUCCESS;										
}											
	
template <class T_ELE>
VOID Vector<T_ELE>::pop_back()                  //实现删除最后一个元素
{
	//m_dwIndex前一个索引就是最后一个元素的索引
	T_ELE x=0;
	memcpy(&m_pVector[m_dwIndex-1],&x,sizeof(x));

	//修改属性
	m_dwIndex-=1;

}				

template <class T_ELE>
DWORD Vector<T_ELE>::capacity()               //在不增容的情况下,返回还能存储多少元素
{
	DWORD x=m_dwLen-m_dwIndex;
	return x;
}

template <class T_ELE>
VOID Vector<T_ELE>::clear()                   //清空所有元素
{
	//初始化所有元素
	memset(&m_pVector[0],0,sizeof(T_ELE)*m_dwLen);

	//修改属性
	m_dwIndex=0;

}

template <class T_ELE>
DWORD Vector<T_ELE>::size()                   //返回已有元素数量
{
	//返回已有元素数量
	return m_dwIndex;

}

template <class T_ELE>                       //判断Vector是否为空
BOOL Vector<T_ELE>::empty()
{
	if(m_dwIndex==0)
		return true;
	else
		return false;
}

template <class T_ELE>
DWORD Vector<T_ELE>::erase(DWORD dwIndex)
{
	//判断接收索引是否非法
	if(dwIndex>=m_dwIndex || dwIndex<0)
		return m_INDEX_ERROR;
	//判断元素个数是否为0
	if(m_dwIndex!=0)
	{
	//删除指定索引元素
		for(int i=dwIndex;i<m_dwIndex;i++)
		{
			memcpy(&m_pVector[i],&m_pVector[i+1],sizeof(T_ELE));
		}
		//将最后一个元素初始化
		memset(&m_pVector[m_dwIndex-1],0,sizeof(T_ELE));
	}

	//修改属性
	m_dwIndex-=1;
}
	
//其他函数。。自己实现	
void Test()
{
	Vector<int>* pVector=new Vector<int>(4);
	pVector->push_back(1);
	pVector->push_back(2);
	pVector->push_back(3);
	pVector->push_back(4);
	//pVector->insert(0,9);
    /*
	int x=0;
	pVector->at(3,&x);
	printf("%d\n",x);
	pVector->pop_back();
	pVector->at(3,&x);
	printf("%d\n",x);
	*/
	//printf("%d\n",pVector->capacity());
	//pVector->clear();
	//printf("%d\n",pVector->size());
	//printf("%d\n",pVector->empty());
	pVector->erase(0);
}
int main()
{
	Test();

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值