Создание аллокаторов памяти
#include <iostream>
#include <memory>
#include "Triangle. h"
#include "TStack. h"
// template stack on shared_ptr with iterator
int main(int argc, char** argv) {
TStack<Triangle> stack;
stack. push(std::shared_ptr<Triangle>(new Triangle(1,1,1)));
stack. push(std::shared_ptr<Triangle>(new Triangle(2,2,2)));
stack. push(std::shared_ptr<Triangle>(new Triangle(3,3,3)));
for(auto i : stack) std::cout << *i << std::endl;
return 0;
}
Лабораторная работа №6
Цель работы
Целью лабораторной работы является:
· Закрепление навыков по работе с памятью в C++.
· Создание аллокаторов памяти для динамических структур данных.
Задание
Используя структуры данных, разработанные для предыдущей лабораторной работы (ЛР№5) спроектировать и разработать аллокатор памяти для динамической структуры данных.
Цель построения аллокатора – минимизация вызова операции malloc. Аллокатор должен выделять большие блоки памяти для хранения фигур и при создании новых фигур-объектов выделять место под объекты в этой памяти.
Алокатор должен хранить списки использованных/свободных блоков. Для хранения списка свободных блоков нужно применять динамическую структуру данных (контейнер 2-го уровня, согласно варианта задания).
Для вызова аллокатора должны быть переопределены оператор new и delete у классов-фигур.
Нельзя использовать:
· Стандартные контейнеры std.
Программа должна позволять:
· Вводить произвольное количество фигур и добавлять их в контейнер.
· Распечатывать содержимое контейнера.
· Удалять фигуры из контейнера.
Полезный пример
Данный пример демонстрирует основные возможности языка C++, которые понадобится применить в данной лабораторной работе. Пример не является решением варианта лабораторной работы.
Листинг файла TAllocationBlock. h
#ifndef TALLOCATIONBLOCK_H
#define TALLOCATIONBLOCK_H
#include <cstdlib>
class TAllocationBlock {
public:
TAllocationBlock(size_t size, size_t count);
void *allocate();
void deallocate(void *pointer);
bool has_free_blocks();
virtual ~TAllocationBlock();
private:
size_t _size;
size_t _count;
char *_used_blocks;
void **_free_blocks;
size_t _free_count;
};
#endif /* TALLOCATIONBLOCK_H */
Листинг файла TAllocationBlock. cpp
#include "TAllocationBlock. h"
#include <iostream>
TAllocationBlock::TAllocationBlock(size_t size, size_t count): _size(size),_count(count) {
_used_blocks = (char*)malloc(_size*_count);
_free_blocks = (void**)malloc(sizeof(void*)*_count);
for(size_t i=0;i<_count;i++) _free_blocks[i] = _used_blocks+i*_size;
_free_count = _count;
std::cout << "TAllocationBlock: Memory init" << std::endl;
}
void *TAllocationBlock::allocate() {
void *result = nullptr;
if(_free_count>0)
{
result = _free_blocks[_free_count-1];
_free_count—;
std::cout << "TAllocationBlock: Allocate " << (_count-_free_count) << " of " << _count << std::endl;
} else
{
std::cout << "TAllocationBlock: No memory exception :-)" << std::endl;
}
return result;
}
void TAllocationBlock::deallocate(void *pointer) {
std::cout << "TAllocationBlock: Deallocate block "<< std::endl;
_free_blocks[_free_count] = pointer;
_free_count ++;
}
bool TAllocationBlock::has_free_blocks() {
return _free_count>0;
}
TAllocationBlock::~TAllocationBlock() {
if(_free_count<_count) std::cout << "TAllocationBlock: Memory leak?" << std::endl;
else std::cout << "TAllocationBlock: Memory freed" << std::endl;
delete _free_blocks;
delete _used_blocks;
}
Листинг файла TIterator. h
#ifndef TITERATOR_H
#define TITERATOR_H
#include <memory>
#include <iostream>
template <class node, class T>
class TIterator
{
public:
TIterator(std::shared_ptr<node> n) {
node_ptr = n;
}
std::shared_ptr<T> operator * (){
return node_ptr->GetValue();
}
std::shared_ptr<T> operator -> (){
return node_ptr->GetValue();
}
void operator ++ (){
node_ptr = node_ptr->GetNext();
}
TIterator operator ++ (int){
TIterator iter(*this);
++(*this);
return iter;
}
bool operator == (TIterator const& i){
return node_ptr == i. node_ptr;
}
bool operator!= (TIterator const& i){
return!(*this == i);
}
private:
std::shared_ptr<node> node_ptr;
};
#endif /* TITERATOR_H */
Листинг файла TStack. h
#ifndef TSTACK_H
#define TSTACK_H
#include "TIterator. h"
#include "TStackItem. h"
#include <memory>
template <class T> class TStack {
public:
TStack();
void push(std::shared_ptr<T> &&item);
bool empty();
TIterator<TStackItem<T>,T> begin();
TIterator<TStackItem<T>,T> end();
std::shared_ptr<T> pop();
template <class A> friend std::ostream& operator<<(std::ostream& os, const TStack<A>& stack);
virtual ~TStack();
private:
std::shared_ptr<TStackItem<T>> head;
};
#endif /* TSTACK_H */
Листинг файла TStack. cpp
#include "TStack. h"
template <class T> TStack<T>::TStack() : head(nullptr) {
}
template <class T> std::ostream& operator<<(std::ostream& os, const TStack<T>& stack) {
std::shared_ptr<TStackItem<T>> item = stack. head;
while(item!=nullptr)
{
os << *item;
item = item->GetNext();
}
return os;
}
template <class T> void TStack<T>::push(std::shared_ptr<T> &&item) {
std::shared_ptr<TStackItem<T>> other(new TStackItem<T>(item));
other->SetNext(head);
head = other;
}
template <class T> bool TStack<T>::empty() {
return head == nullptr;
}
template <class T> std::shared_ptr<T> TStack<T>::pop() {
std::shared_ptr<T> result;
if (head!= nullptr) {
result = head->GetValue();
head = head->GetNext();
}
return result;
}
template <class T> TIterator<TStackItem<T>,T> TStack<T>::begin()
{
return TIterator<TStackItem<T>,T>(head);
}
template <class T> TIterator<TStackItem<T>,T> TStack<T>::end()
{
return TIterator<TStackItem<T>,T>(nullptr);
}
template <class T> TStack<T>::~TStack() {
}
#include "Triangle. h"
template class TStack<Triangle>;
template std::ostream& operator<<(std::ostream& os, const TStack<Triangle>& stack);
Листинг файла TStackItem. h
#ifndef TSTACKITEM_H
#define TSTACKITEM_H
#include <memory>
#include "TAllocationBlock. h"
template<class T> class TStackItem {
public:
TStackItem(const std::shared_ptr<T>& triangle);
template<class A> friend std::ostream& operator<<(std::ostream& os, const TStackItem<A>& obj);
std::shared_ptr<TStackItem<T>> SetNext(std::shared_ptr<TStackItem> &next);
std::shared_ptr<TStackItem<T>> GetNext();
std::shared_ptr<T> GetValue() const;
void * operator new (size_t size);
void operator delete(void *p);
virtual ~TStackItem();
private:
std::shared_ptr<T> item;
std::shared_ptr<TStackItem<T>> next;
static TAllocationBlock stackitem_allocator;
};
#endif /* TSTACKITEM_H */
Листинг файла TStackItem. cpp
#include "TStackItem. h"
#include <iostream>
template <class T> TStackItem<T>::TStackItem(const std::shared_ptr<T>& item) {
this->item = item;
this->next = nullptr;
std::cout << "Stack item: created" << std::endl;
}
template <class T> TAllocationBlock TStackItem<T>::stackitem_allocator(sizeof(TStackItem<T>),100);
template <class T> std::shared_ptr<TStackItem<T>> TStackItem<T>::SetNext(std::shared_ptr<TStackItem<T>> &next) {
std::shared_ptr<TStackItem < T>> old = this->next;
this->next = next;
return old;
}
template <class T> std::shared_ptr<T> TStackItem<T>::GetValue() const {
return this->item;
}
template <class T> std::shared_ptr<TStackItem<T>> TStackItem<T>::GetNext() {
return this->next;
}
template <class T> TStackItem<T>::~TStackItem() {
std::cout << "Stack item: deleted" << std::endl;
}
template <class A> std::ostream& operator<<(std::ostream& os, const TStackItem<A>& obj) {