空间配置器allocator
自己定义的vector容器
缺点
- 构造容器的时候使用new导致分配内存的同时也调用构造函数,析构容器的时候使用delete将所有的元素进行析构。我们想要的是在使用容器的时候,如果没有元素入栈,就不会进行多余的构造;同时对容器进行析构时,也仅仅析构仅有的几个元素。
#include <iostream>
template<typename T>
class vector {
public:
vector(int size) {
_first = new T[size];
_last = _first;
_end = _first + size;
}
vector(const vector<T>& rhs) // 容器的拷贝构造函数
{
int size = rhs._end - rhs._first;
int len = rhs._last - rhs._first;
_first = new T[size];
for (int i = 0; i < len; i++)
{
_first[i] = rhs._first[i];
}
_last = _first + len;
_end = _first + size;
}
vector& operator=(const vector<T>& rhs) // 赋值运算重载
{
if (this == &rhs)
return *this;
delete[]_first;
int size = rhs._end - rhs._first;
int len = rhs._last - rhs._first;
_first = new T[size];
for (int i = 0; i < len; i++)
{
_first[i] = rhs._first[i];
}
_last = _first + len;
_end = _first + size;
return *this;
}
~vector()
{
delete[]_first;
_first = _last = _end = nullptr;
}
// 向容器末尾添加参数
void pushback(T val)
{
if (full())
{
expand();
}
*_last++ = val;
}
void popback()
{
if (empty())
return;
_last--;
}
T back() // 返回容器末尾的元素值
{
return *_last;
}
bool full()
{
return _last == _end;
}
bool empty()
{
return _first == _last;
}
T top()
{
return *(_last - 1);
}
private:
void expand() // 容器二倍扩容
{
int size = _end - _first;
T* tmp = new T[2 * size];
int len = _last - _first;
for (int i = 0; i <= len; i++)
{
tmp[i] = _first[i];
}
delete[]_first;
_first = tmp;
}
T* _first; // 指向容器起始元素地址
T* _last; // 指向容器末尾元素地址
T* _end; // 指向分配内存某位地址
};
class Test
{
public:
Test() { std::cout << "Test()::construct" << std::endl; }
~Test() { std::cout << "~Test()::construct" << std::endl; }
Test(const Test& rhs) { std::cout << " Test(const Test& rhs)::construct" << std::endl; }
private:
};
int main()
{
vector<Test>vec(10);
return 0;
}
使用allocator空间配置器
-
通过定义空间配置器,使内存开辟、内存释放与构造、析构分离,这样可以使得定义容器时不会直接在容器内部调用构造函数,而是在为容器添加元素或者删除元素时调用构造函数或者析构函数
-
空间配置器组成:
-
内存分配T* allocate(size_t size)
T* allocate(size_t size) { T *ptr = (T*)malloc(sizeof(T) * size); return ptr; }
-
内存释放void deallocate(T *p)
// 释放内存空间 void deallocate(T *ptr) { free(ptr); }
-
对象构造 void construct(T *p, const T &val)
// 构造对象 void construct(T *ptr, const T &val) { new (ptr) T(val); // 定位new }
-
对象析构 void destroy(T *p)
// 析构对象 void destroy(T *ptr) { ptr->~T(); }
-
整体代码
#include <iostream>
// 定义空间配置器 ;SGI二级空间配置器:内存池
template<typename T>
class Allocator {
public:
// 开辟内存空间
T* allocate(size_t size) {
T *ptr = (T*)malloc(sizeof(T) * size);
return ptr;
}
// 释放内存空间
void deallocate(T *ptr)
{
free(ptr);
}
// 构造对象
void construct(T *ptr, const T &val)
{
new (ptr) T(val); // 定位new
}
// 析构对象
void destroy(T *ptr)
{
ptr->~T();
}
};
template<typename T, typename Alloc = Allocator<T>>
class vector {
public:
vector(int size) {
_first = allocator_.allocate(size);
_last = _first;
_end = _first + size;
}
vector(const vector<T>& rhs) // 容器的拷贝构造函数
{
int size = rhs._end - rhs._first;
int len = rhs._last - rhs._first;
_first = allocator_.allocate(size);
for (int i = 0; i < len; i++)
{
allocator_.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
}
vector& operator=(const vector<T>& rhs) // 赋值运算重载
{
if (this == &rhs)
return *this;
delete[]_first;
int size = rhs._end - rhs._first;
int len = rhs._last - rhs._first;
_first = allocator_.allocate(size);
for (int i = 0; i < len; i++)
{
allocator_.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
return *this;
}
~vector()
{
//delete[]_first;
for (int i = 0; i < _last - _first; i++)
{
allocator_.destroy(_first + i);
}
allocator_.deallocate(_first);
_first = _last = _end = nullptr;
}
// 向容器末尾添加参数
void pushback(const T &val)
{
if (full())
{
expand();
}
//*_last++ = val;
allocator_.construct(_last++, val);
}
void popback()
{
if (empty())
return;
--_last;
allocator_.destroy(_last);
}
T back() // 返回容器末尾的元素值
{
return *(_last - 1);
}
bool full()
{
return _last == _end;
}
bool empty()
{
return _first == _last;
}
T top()
{
return *(_last - 1);
}
private:
void expand() // 容器二倍扩容
{
int size = _end - _first;
T* tmp = allocator_.allocate(size * 2);
int len = _last - _first;
for (int i = 0; i <= len; i++)
{
allocator_.construct(tmp + i, _first[i]);
}
for (int i = 0; i <= len; i++)
{
allocator_.destroy(_first + i);
}
allocator_.deallocate(_first);
_first = tmp;
_last = _first + len;
_end = _first + size * 2;
}
Alloc allocator_;
T* _first; // 指向容器起始元素地址
T* _last; // 指向容器末尾元素地址
T* _end; // 指向分配内存某位地址
};
class Test
{
public:
Test() { std::cout << "Test()::construct" << std::endl; }
~Test() { std::cout << "~Test()::construct" << std::endl; }
Test(const Test& rhs) { std::cout << " Test(const Test& rhs)::construct" << std::endl; }
private:
};
int main()
{
vector<Test>vec(10);
Test t1;
Test t2;
Test t3;
std::cout << "-----------------" << std::endl;
vec.pushback(t1);
vec.pushback(t2);
vec.pushback(t3);
std::cout << "-----------------" << std::endl;
vec.popback();
std::cout << "-----------------" << std::endl;
return 0;
}
标签:last,int,rhs,配置,._,空间,first,allocator,size
From: https://blog.csdn.net/weixin_43459437/article/details/143148899