c++ primer 5th 练习 13.6.2

本文介绍了一个简易String类及StrVec类的实现,重点在于移动构造函数和移动赋值运算符的设计与应用。通过具体代码展示了如何利用C++标准库中的allocator进行资源管理,以及如何在类中实现高效的移动语义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

13.49为你的StrVec、String和Message类添加一个移动构造函数和移动赋值运算符

String:

// 自己的简易String.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <memory>
#include <vector>
#include <utility>
using namespace std;

static allocator<char> alloc;

class String
{
public:
	String() :elements(NULL), cap(NULL), first_free(NULL) {};
	String(const char*);
	String(const String&);
	String& operator=(const String & ) ;

	String(String && s)noexcept :
		elements(s.elements), first_free(s.first_free), cap(s.cap)
	{
		s.elements = s.first_free = s.cap = NULL;
	}
	String & operator =(String&& s) 
	{
		elements = s.elements;
		first_free = s.first_free;
		cap = s.cap;
		s.elements = s.first_free = s.cap = NULL;
		return *this;
	}

	~String();
	void insert(char);
	int size() { return first_free - elements; };
	int capcity() { return cap - elements; };
	bool empty() { return first_free - elements ? false : true; };

	void check_n();
	void relo();
	void free();
	void out();

	char *begin() { return elements; }
	char *end() { return first_free; }

private:
	char *elements;
	char *cap;
	char *first_free;

};

void String::out()
{
	auto temp_l = elements;
	while (temp_l != first_free)
		cout << *temp_l++;
	cout << endl;
}

void String::check_n()
{
	if (!(cap - first_free))
		relo();
}

void String::free()
{
	auto temp_fir = first_free;
	while (temp_fir != elements)
		alloc.destroy(--temp_fir);
	alloc.deallocate(elements, capcity());
}

void String::relo()
{
	int leth;
	leth = elements ? capcity() * 2 : 1;
	auto temp_elem = alloc.allocate(leth);
	uninitialized_copy(elements, first_free, temp_elem);

	auto temp_first = temp_elem + size();
	auto temp_cap = temp_elem + leth;
	free();
	elements = temp_elem;
	first_free = temp_first;
	cap = temp_cap;
}

void String::insert(char c)
{
	check_n();
	alloc.construct(first_free++, c);
}

String::String(const char *c)
{
	for (int a = 0;*(c+a) != '\0'; a++)
		insert(*(c+a));
}

String::String(const String &s)
{
	int size = s.first_free - s.elements;
	elements = alloc.allocate(size);
	cap = first_free = elements+size;
	auto temp_s = s.elements;
	auto temp_ele = elements;
	while (temp_s != s.first_free)
		*temp_ele++ = *temp_s++;
	//cout << " copy " << endl;
}

String& String::operator=(const String &s)
{
	int size = s.first_free - s.elements;
	auto new_elem = alloc.allocate(size);
	auto new_first_free = new_elem;
	auto temp_ele = s.elements;
	for (auto i = s.elements; i != s.first_free; i++)
	{
		alloc.construct(new_first_free++, *(temp_ele++));
	}
	//cout << "run '=' once" << endl;
	free();
	elements = new_elem;
	first_free = new_first_free;
	cap = new_elem + size;
	return *this;
}



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

int main()
{
	String s("dizi");
	String s1("xiao");
	s.out();
	s1.out();

	String t(std::move(s));
	String t1;
	t1 = std::move(s1);

	t.out();
	t1.out();

	s.out();
	s1.out();

	
	system("pause");
	return 0;
}

StrVec


#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <utility>
#include <fstream>
#include <algorithm>

using namespace std;

static std::allocator<string> alloc;

class StrVec
{
public:
	StrVec() :
		elements(NULL), first_free(NULL), cap(NULL) {};
	StrVec(initializer_list<string> s);
	StrVec(const StrVec&);
	StrVec &operator=(const StrVec&);
	StrVec(StrVec&&s) :
		elements(s.elements), first_free(s.first_free), cap(s.cap)
	{
		s.elements = s.first_free = s.cap = NULL;
	}
	StrVec & operator = (StrVec&&s)
	{
		elements = s.elements;
		first_free = s.first_free;
		cap = s.cap;
		s.elements = s.first_free = s.cap = NULL;
		return *this;
	}
	~StrVec();

	void push_back(const string &);
	int size() { return first_free - elements; };                     //容器内元素哥数
	int capcity() { return cap - elements; };                         //可用容器大小
	bool empty() { return size() ? 1 : 0; }
	void pop_back() { alloc.destroy(--first_free); };
	string &front() { return *elements; };
	string &back() { return *(first_free-1); }

	string *begin() { return elements; };
	string *end() { return first_free; };

	void resize(int i);
	void resize(int i, const string &s);
	void reserve(int i);

private:
	void check_n_size();                  //  检查是否有可用空间函数
	void relocate();                      //  重新分配空间,并拷贝的函数
	void free();                          //  释放内存函数
	pair<string*, string*> allc_n_copy(); //  工具函数,拷贝,赋值使用

										  //static std::allocator<string> alloc;  内存分配器,甩出指针,指向分配得内存
	string *elements;                     //  内存开头
	string *first_free;                   //  第一个可用内存地址
	string *cap;                          //  尾后指针
};

StrVec::StrVec(const StrVec & sv)
{
	auto newdata = alloc.allocate(sv.first_free - sv.elements);
	uninitialized_copy(sv.elements, sv.first_free, newdata);
	elements = newdata;
	first_free = cap = elements + (sv.first_free - sv.elements);
}

StrVec::StrVec(initializer_list<string> init_l)
{
	elements = first_free = cap = NULL;
	for (auto a : init_l)
		push_back(a);
}

StrVec & StrVec::operator=(const StrVec & sv)
{
	//初始版本
	/*auto newdata = alloc.allocate(sv.first_free - sv.elements);
	uninitialized_copy(sv.elements, sv.first_free, newdata);
	free();
	elements = newdata;
	first_free = cap = elements + (sv.first_free - sv.elements);
	return *this;	 */
	//加入 allc_n_copy版本 逻辑更清洗
	auto newdata = allc_n_copy();
	uninitialized_copy(sv.elements, sv.first_free, newdata.first);
	free();
	elements = newdata.first;
	first_free = cap = newdata.second;
	return *this;
}

pair<string *, string*> StrVec::allc_n_copy()
{
	auto newele = alloc.allocate(first_free - elements);
	auto newcap = newele + (first_free - elements);
	return pair<string*, string*>{newele, newcap};
}

void StrVec::free()
{
	/*if (elements)
		for (auto a = first_free; a != elements;)
			alloc.destroy(--a);
	alloc.deallocate(elements, capcity());*/

	//for_each版本 
	if (elements)
	{
		for_each(elements, first_free - 1,
			[](string &s) { alloc.destroy(&s); });
		alloc.deallocate(elements, capcity());
	}
		

}
void StrVec::check_n_size()
{
	if (size() == capcity())
		relocate();
}

void StrVec::relocate()
{
	//	//自己写的版本
	//	int i, j;
	//	string *newdata;
	//	if (elements == NULL)
	//	{
	//		newdata = alloc.allocate(1);
	//		i = 0;
	//		j = 1;
	//	}
	//	else
	//	{
	//		newdata = alloc.allocate(size() * 2);
	//		i = first_free - elements;
	//		j = size() * 2;
	//		uninitialized_copy(elements, first_free, newdata);
	//		free();
	//	}
	//	elements = newdata;
	//	first_free = newdata + i;
	//	cap = newdata + j;
	//使用move
	auto newcapcity = capcity() ? 2 * capcity() : 1;
	auto newelements = alloc.allocate(newcapcity);
	auto temp_ele = elements;
	auto temp_bg = newelements;
	for (int i = 0; i < size(); i++)
		alloc.construct(temp_bg++, std::move(*temp_ele++));
	free();
	elements = newelements;
	first_free = temp_bg;
	cap = elements + newcapcity;
}

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

void StrVec::push_back(const string &s)
{
	check_n_size();
	alloc.construct(first_free++, s);
}

void StrVec::resize(int i)
{
	// 需要容器内元素数量小于当前实际元素数量,则析构i之后的元素
	if (i < size())
	{
		while (size() != i)
			alloc.destroy(--first_free);
	}
	// 需要容量大于 size() 小于  capcity() 则什么都不做
	// 需要容量大于 capcity(),重新分配内存,容量翻倍
	while (capcity() < i)
		relocate();
}

void StrVec::resize(int i, const string &s)
{
	// 需要容器内元素数量小于当前实际元素数量,则析构i之后的元素
	if (i < size())
	{
		while (size() != i)
			alloc.destroy(--first_free);
	}
	// 需要容量大于 size() 小于  capcity() 则什么都不做
	// 需要容量大于 capcity(),重新分配内存,容量翻倍,并初始化
	if (i > capcity())
	{
		while (capcity() < i)
			relocate();
		while (size() < i)
			alloc.construct(first_free++, s);
	}
}

void StrVec::reserve(int n)
{
	if (n > capcity())
		while (capcity() < n)
			relocate();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值