设为首页 加入收藏

TOP

<四>理解空间配置器allocator, 优化STL 中的Vector(一)
2023-07-23 13:34:17 】 浏览:56
Tags:< > 解空间 allocator 优化 STL Vector

.在上一节我们实现的 MyVector存在哪些问题?

问题1

现在有Student类
class Student{
   public:
   Student(){cout<<"构造Student对象"<<endl;}
   ~Student(){cout<<"析构Student对象"<<endl;}
   private:
       int   age
       char  NAME[20];
       char  *pAddress;
}

MyVector<Student> v1[1000];

我只是希望创建一个能放1000个Student 的Vector,但是开始并不放任何内容,但是发现编译器除分配了1000个student对象的空间,还创建了1000个对象,
在main函数结束后再析构这1000个对象,这就是问题1,这1000个对象并不是我需要的,
原因如下,在MyVector的构造函数中 T * _tep = new T[size](); 这个new除了分配空间,还会调用对象的构造函数完成对象的初始化
换句话说就是 空间的分配和对象的创建联系在了一起,这个非常不合理,我们需要把他分开,我希望是需要帮我开辟空间即可,不希望帮我创建1000个对象

问题2关于析构函数

//析构函数
~MyVector<T>() {
	if (Empty() == false) {
		delete[]first;
		first = nullptr;
		last  = nullptr;
		end   = nullptr;
		cout << "析构Vector,堆地址"<<first << endl;
	}

}

实际情况时,我的vector是可以放1000个student对象的容器,但是实际里面可能暂时只放了100个对象,
而delete[] first,是把整个vector中的1000个student对象都调用析构函数,这也不合理,我们只需要析构有效
数量的对象然后再释放first指针指向的堆内存

问题3 关于添加元素和删除元素

student s1;
student s2;
student s3;

MyVector<student> v1(1000);// 这一句编译器会先分配1000个student对象空间,然后再调用1000次构造函数创建1000个student对象


v1.pushback(s1);
//上面这句话会调用赋值函数,会将s1的内容赋值给已经在堆上的student对象,但实际上我想要的是,只需要将分配好的空间
//给我,我使用拷贝构造,将s1拷贝构造出来一个对象放在你给的空间上,这是个问题


v1.popBack(){
    this->last--;
}
//上面的pop最后一个studnet对象,只是将最后一个元素的指针前移动一个student空间大小,并没有去析构这个对象,
//而且这个弹出的student对象里面有一个char *pAddress 指向了外部堆内存资源,这个内存自己没有去释放的话,
//造成了内存泄漏了. 这个也是个问题,所以说我们要去析构这个弹出的student对象但是不能使用delete方式delete这个对象,为什么呢?
//因为delete调用完析构函数,他还要free释放内存空间,但是这个空间属于Vector的,释放掉了这一小块空间,我们后面就无法在使用了,
//**所以一句话就是我们从vector中删除一个对象时,只做析构这个对象但不释放他的内存空间,需要把对象的析构和内存的释放分开**

以上三个问题使得我们不能采用上一篇文字中的方式写Vector,这就是引入了容器的空间配置器的原因

容器的空间配置器做了4件事
内存开辟/内存释放 对象创建/对象析构

在上一遍的基础上加入空间配置器,代码如下

#include <iostream>
using namespace std;


class student {

public:

	student(int _age, char * _pname): 
		age(_age),
		pName(_pname){  
	}

	student(const student & _rvalue) {
		this->age = _rvalue.age;
		this->pName = new char[20];
		strcpy(this->pName, _rvalue.pName);
	}

	student & operator =(const student & _rvalue) {
		
		if (this == &_rvalue) { return *this; }
		
		delete[]this->pName;
		this->pName = nullptr;

		this->age = _rvalue.age;	
		this->pName = new char[20];
		strcpy(this->pName, _rvalue.pName);
	}
	~student() {
		delete[] this->pName;
		this->pName == nullptr;
		cout << "student 析构函数被执行,当前对象地址是" << this << endl;
	}


private:
	int age;
	char *pName;
};


template<typename T>
class MyAllocate {

public:

	T * allocate(int size) {
		return (T *)malloc(sizeof(T)*size);
	}

	//根据指定的地址,释放内存空间
	void delAllocate(T *p) {
		free(p);
	}

	//在p指针指定的位置,根据指定的对象创建新对象
	void construct(T * p, const T & _rValue) {
		new (p) T(_rValue);
	}

	//析构指定对象,但不释放内存空间
	void destory(T * p) {
		if (p != nullptr) {
			p->~T();
		}
	}



};



template<typename T, typename Allocate=MyAllocate<T>>
class MyVector2 {

public:

	//构造函数
	MyVector2<T, Allocate>(int size = 10, const Allocate & _allocate = MyAllocate<T>()) : allocator(_allocate) {
		
		first = allocator.allocate(size);
		last = first;
		end = first + size;
		cout << "MyVector2 构造函数,构建数量=" <&l
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇<三>使用类模板实现STL Vec.. 下一篇SLAM十四讲CH8代码

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目