1. 程式人生 > >動態記憶體管理allocator類C++ STL標準模板庫vector實現

動態記憶體管理allocator類C++ STL標準模板庫vector實現

//vector.h
#ifndef NSTL_VECTOR_H_
#define NSTL_VECTOR_H_
#include <memory>
#include <string>

namespace nstl {
	class vector {
	public:
		vector() : elements(nullptr), first_free(nullptr), cap(nullptr) {
		}
		vector(const vector&);
		vector& operator= (const vector&);
		~
vector(); void push_back(const std::string&); size_t size() const { return first_free - elements; } size_t capacity() const { return cap - elements; } std::string* begin() const { return elements; } std::string* end() const { return first_free; } private: static std::
allocator<std::string> alloc; void chk_n_alloc() { if (size() == capacity()) { reallocate(); } } std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*); void free(); void reallocate(); std::string* elements; std::string* first_free;
std::string* cap; }; } #endif
//vector.cpp
#include "vector.h"
using namespace nstl;

std::allocator<std::string> vector::alloc;

vector::vector(const vector& str) {
	auto data = alloc_n_copy(str.begin(), str.end());
	elements = data.first;
	first_free = cap = data.second;
}

vector::~vector() {
	free();
}

vector& vector::operator= (const vector& str) {
	auto data = alloc_n_copy(str.begin(), str.end());
	free();
	elements = data.first;
	first_free = cap = data.second;
	return *this;
}

void vector::push_back(const std::string& str) {
	chk_n_alloc();
	alloc.construct(first_free++, str);
}

std::pair<std::string*, std::string*> vector::alloc_n_copy(const std::string* begin, const std::string* end) {
	auto data = alloc.allocate(end - begin);
	//warning C4996: Call to 'std::uninitialized_copy' with parameters that may be unsafe
	return{ data, std::uninitialized_copy(begin, end, data) };
}

void vector::free() {
	if (elements) {
		for (auto p = first_free; p != elements; ) {
			alloc.destroy(--p);
		}
		alloc.deallocate(elements, cap - elements);
	}
}

void vector::reallocate() {
	auto capacity = size() ? 2 * size() : 1;
	auto data = alloc.allocate(capacity);
	auto databak = data;
	auto elembak = elements;
	for (size_t i = 0; i != size(); ++i) {
		//using std::move(string,don't copy construct)
		alloc.construct(databak++, std::move(*elembak++));
	}
	free(); //need elemets, no destructor string
	elements = data;
	first_free = databak;
	cap = elements + capacity;
}

©qingdujun
2018-12-2 於 北京 海淀

References:
C++ Primer(第五版)