自定義簡易string類c++primer13.44

TinnCHEN發表於2019-04-16

標頭檔案

#pragma warning(disable:4996) //可參考上一篇解決c4996問題的部落格
#include<iostream>
#include<memory>
#include<algorithm>
#include<utility>


class String {
public:
	String() { 
		elements = nullptr;
		first_free = nullptr;
	}
	String(char *c) {  //接受c風格的字串,c指向字串第一個字元
		auto c1 = const_cast<char *>(c);
		while (*c1) {
			++c1;
		}
		auto p = alloc_n_copy(c, c1);
		elements = p.first;
		first_free = p.second;
	}
	String(const String& s) {
		auto p = alloc_n_copy(s.elements, s.first_free);
		elements = p.first;
		first_free = p.second;
	}
	String &operator=(const String& s) {
		auto p = alloc_n_copy(s.elements, s.first_free);
		free();
		elements = p.first;
		first_free = p.second;
	}
	~String() {
		free();
	}
	void show() {
		auto p = elements;
		while (p != first_free) {
			std::cout << *p;
			++p;
		}
		std::cout << std::endl;
	}
	size_t size() { return first_free - elements; }
	String &operator+(String& s) {
		auto p = alloc.allocate(this->size() + s.size());
		//註釋部分為拷貝實現
		/*auto dataMid = std::uninitialized_copy(this->elements, this->first_free, p);
		auto dataEnd = std::uninitialized_copy(s.elements, s.first_free, dataMid);
		this->free();
		this->elements = p;
		this->first_free = dataEnd;*/
		//下面採用了移動建構函式std::move,節省了拷貝開銷
		auto dest = p; //指向新陣列中下一個空閒位置
		auto elem = this->elements;  //指向就陣列中下一個元素
		for (size_t i = 0; i != this->size(); ++i) {
			alloc.construct(dest++, std::move(*elem++));
		}
		elem = s.elements;
		for (size_t i = 0; i != s.size(); ++i) {
			alloc.construct(dest++, std::move(*elem++));
		}
		free();
		this->elements = p;
		this->first_free = dest;
		return *this;
	}
private:
	char *elements;  //指向字串首字元
	char *first_free;  //指向字串最後一個字元的後一個位置
    static std::allocator<char> alloc;  //類內靜態成員要在類外進行定義初始化否則會出現LNK2001error
	static std::allocator<char> initalloc() {
		std::allocator<char> allo;
		allo.allocate(1);
		return allo;
	}
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();
};

std::allocator<char> String::alloc = initalloc();

std::pair<char*, char*> String::alloc_n_copy(const char* c1, const char* c2) {
	auto dataBeg = alloc.allocate(c2 - c1);
	auto dataEnd = std::uninitialized_copy(c1, c2, dataBeg);
	return std::make_pair(dataBeg, dataEnd);
}

void String::free() {
	if (elements) {
		std::for_each(elements, first_free, [this](char &rhs) {alloc.destroy(&rhs); });
		alloc.deallocate(elements, first_free - elements);
	}
}

主函式

#include<iostream>
#include"classString.h"

using namespace std;

int main() {
	String s("dasdsad11111");
	s.show();
	String s1(s);
	s1.show();
	String s2 = s;
	s2.show();
	cout << s2.size() << endl;
	s1 + s2;
	s1.show();
	return 0;
}

相關文章