簡化版vector

晚餐吃什麼發表於2018-12-01

參考書上敲了一個簡化版的vector,這裡的簡化主要是指沒有用模板去實現vector,而僅以基於string的vector這個範例來演示其內部的記憶體分配原理:

實現的功能有以下幾點:

  1. 實現了預先保留空間,其記憶體分配策略為擴大兩倍容量。
  2. 基於allocator實現了申請記憶體和初始化物件的分離。
  3. 使用move函式實現string的移動構造。

待實現的功能:

  1. 模板技術
  2. 引用計數
  3. 內部其他方法

程式碼如下:

#include <iostream>
#include <vector>
#include <allocators>
#include <string>


class MyVector {
public:
	MyVector():first(nullptr),first_free(nullptr),last(nullptr){}
	MyVector(const MyVector&v) {
		pair<string*, string*> pir = alloc_copy(v.begin(), v.end());
		first = pir.first;
		first_free =last= pir.second;
	};
	MyVector &operator=(const MyVector&v) {
		free();
		auto data = alloc_copy(v.begin(), v.end());
		first = data.first;
		first_free = data.second;
		return *this;
	};
	~MyVector() { free(); };
	void push_back(const string& s) {
		check_alloc();
		alloc.construct(first_free++, s);
	};
	size_t size() const { return first_free - first; };
	size_t capacity() const { return last - first; };
	string *begin() const { return first; };
	string *end() const { return first_free; };
private:
	static allocator<string> alloc;
	//allocator<string> alloc;
	void check_alloc() {
        //檢查容器是否已滿
		if (size() == capacity())
			reallocate();
	}
	//拷貝構造一段
	pair<string*,string*> alloc_copy(string*begin, string*end) {
		auto data = alloc.allocate(end - begin);
		return make_pair(data, uninitialized_copy(begin, end, data));
	}
	//析構並釋放所有記憶體
	void free() {
		//不能給deallocate傳遞空指標
		if (first) {
			for (auto p = first; p != first_free;) {
				alloc.destroy(p++);
			}
			alloc.deallocate(first, last - first);
		}
	};
	void reallocate() {
        //注意size為0的情況
		int new_alloc =  size()?capacity() * 2:1;
		string *data_start = alloc.allocate(new_alloc);
		string *temp_start = data_start;
		string *temp_first = first;
		for (size_t i = 0; i < size(); i++) {
			alloc.construct(temp_start++, move(*temp_first++));
		}
		free();
		first = data_start;
		first_free = temp_start;
		last = data_start + new_alloc;
	}

	string *first;
	string *first_free;
	string *last;
};

該類的私有屬性:

string *first 是指向動態陣列頭部的指標

string *first_free 是指向動態陣列已使用空間之後的第一個指標(即end)

string *last 是指向動態陣列可使用空間之後的一個指標

相關文章