动态内存管理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(第五版)

猜你喜欢

转载自blog.csdn.net/u012339743/article/details/84727714