C++12(运算符重载)

1.定义

在这里插入图片描述

2.运算符重载机制的实现(通过函数实现)

class CInt
{
public:
	CInt(int val)
		:value(val){}
	bool operator<(int rhs)//类中   _thiscall  this
	{
		return value < rhs;
	}
	//前置++   后置++
	//标志 
	const CInt operator++(int)//后置++就是先做个备份,用临时量先存储起来(临时量是常量),因此const
	{
		CInt tmp(*this);//局部对象----》备份
		value++;
		return tmp;
	}
	
	CInt& operator++() //返回的就是本身,别名
	{
		++value;
		return *this;
	}
	int& operator[](int* parr)
	{
		return parr[value];
	}
private:
	int value;
};
int main()
{
	int arr[] = { 1, 32, 35, 43, 65, 8 };
	int len = sizeof(arr) / sizeof(arr[0]);
	for (CInt i = 0; i < len; i++)
	{
		std::cout << i[arr] << " ";
	}
	std::cout << std::endl;
	return 0;
}

在这里插入图片描述

3.复数类

在这里插入图片描述

class CComplex//复数类
{
public:
	CComplex(int real, int image)
		:mreal(real), mimage(image)
	{}
	const CComplex operator+(int rhs)  //放在临时量中,&不生成临时量
	{
		return CComplex(mreal + rhs, mimage);
	}
	friend const CComplex operator+(int, const CComplex&);

	bool operator>(const CComplex& lhs)
	{
		return (mreal > lhs.mreal) || ((mreal == lhs.mreal) && (mimage > lhs.mimage));
	}
	bool operator==(const CComplex& rhs)
	{
		return (mreal == rhs.mreal) && (mimage == rhs.mimage);
	}
	friend std::istream& operator>>(std::istream&, CComplex&);
	friend std::ostream& operator<<(std::ostream&, const CComplex&);

private:
	int mreal;
	int mimage;
};
//_cdecl
const CComplex operator+(int lhs, const CComplex& rhs)  //cdcl调用约定,meiyouthis指针,左右操作数都要通过形参传递
{
	return CComplex(lhs + rhs.mreal, rhs.mimage); //访问类内的私有成员变量,破坏了封装性,因此采用友元函数
}

std::ostream& operator<<(std::ostream& out, const CComplex& rhs)//输出流为什么用引用?
//一个程序分配一个输出缓冲区。cout绑定了一个输出缓冲区,如果out不是引用类型,就意味着需要两个缓冲区,所以out应该是&类型
{
	out << rhs.mreal << "<==>" << rhs.mimage;
	return out;
}
std::istream& operator>>(std::istream& in, CComplex& rhs)//rhs不是const类型,因为输入的cc2是变量
{
	in >> rhs.mreal;
	in >> rhs.mimage;
	return in;
}

int main()
{
	CComplex cc1(10, 20);
	CComplex cc2 = cc1 + 10;//V
	CComplex cc3 = 10 + cc1;//在类外实现,因为this指针指向的是对象所占的内存空间,所以指向的只能是cc1,对于此表达式顺序的合适,因此要在类外单独实现(叫全局的方法,cdcl调用约定)
	if (cc2 > cc1)//V
	{
		std::cout << cc2 << std::endl;   //把cc2流入cout中,当输出流关闭之后,把数值打印到屏幕上
	}
	if (cc3 == cc2)//V
	{
		std::cout << cc1 << std::endl;
	}
	std::cin >> cc2;
	std::cout << cc2 << std::endl;
	return 0;
}

4.String类

#include<iostream>

#pragma warning (disable:4996)
class String
{
public:
	String(const char* ptr)
		:mptr(new char[strlen(ptr)+1]())
	{
		strcpy_s(mptr, strlen(ptr) + 1, ptr);
	}
	String(const String& rhs)
	{
		mptr = new char[strlen(rhs.mptr) + 1]();
		strcpy_s(mptr, strlen(rhs.mptr) + 1, rhs.mptr);
	}
	const String operator+(char* rhs)
	{
		char* tmp = new char[strlen(mptr) + strlen(rhs)+1]();
		strcpy_s(tmp, strlen(mptr) + 1, mptr);
		strcat(tmp, rhs);
		String str(tmp);
		delete[] tmp;
		return str;
	}
	const String operator+(const String& rhs)
	{
		char* tmp = new char[strlen(rhs.mptr) + strlen(mptr) + 1]();
		strcpy_s(tmp, strlen(mptr) + 1, mptr);
		strcat(tmp,rhs.mptr);
		String lhs(tmp);
		delete[] tmp;
		return lhs;
	}
	friend const String operator+(const char*, const String&);
	bool operator<(const String& str)
	{
		return strcmp(mptr, str.mptr) < 0;
	}
	bool operator!=(const String& str)
	{
		return strcmp(mptr,str.mptr)!=0;
	}
	char& operator[](int index)//[]运算符重载函数
	{
		return mptr[index];
	}
	friend std::ostream& operator<<(std::ostream&, const String&);
	friend std::ostream& operator>>(std::ostream&, const String&);
private:
	char* mptr;
};
const String operator+(const char* str,const String& rhs)
{
	char* tmp = new char[strlen(str) + strlen(rhs.mptr) + 1]();
	strcpy_s(tmp, strlen(str) + 1, str);
	strcat(tmp, rhs.mptr);
	String lhs(tmp);
	delete[] tmp;
	return lhs;
}
std::ostream& operator<<(std::ostream& out, const String& str)
{
	out << str.mptr << " ";
	return out;
}

int main()
{
		std::string str1("hello");
	//std::string str2("world");

	//std::cout << str1[0] << std::endl; //str是对象,不是指针,所以要写[]运算符重载函数
	std::string::iterator it = str1.begin();//把it对象当作指针来使用
		//面向对象的指针:以对象的形式存在,但是做的却是指针的事
	while (it != str1.end())
	{
		std::cout << *it;//*it是对象的解引用,要实现一个解引用运算符重载函数
		it++;  //++就实现了getnext函数
	}
//	String str1("hello");
//	String str2 = str1 + " world";//除了运算符重载+,还有一个深拷贝(拷贝构造),将值赋给str2
//	String str3 = "hi " + str1;
//	String str4 = str1 + str2;

//	if (str1 < str2)
//	{
//		std::cout << str1 << std::endl;
//	}
	//std::cout << str2 << std::endl;测试用例
	//std::cout << str3 << std::endl;
//	if (str3 != str4)
//	{
//		std::cout << str4 << std::endl;
//	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.iterator迭代器

#include<iostream>
class String;
class Iterator
{
public:
	Iterator(String* ps, int idx)
		:pstr(ps),index(idx)
	{}
	bool operator!=(const Iterator rhs)
	{
		return index = rhs.index;
	}
	
	char& operator*();// 特殊,this指针接收右操作数(平时都是左边)
	const Iterator operator++(int)//后置++
	{
		Iterator tmp(*this);
		index++;
		return tmp;
	}
	Iterator& operator++()
	{
		index++;
		return *this;
	}
	
private:
	String* pstr;//指向String类型的对象
	int index;//下标标识
};

#pragma warning (disable:4996)
class String
{
public:
	typedef Iterator iterator;
	String(char* ptr)
		:mptr(new char[strlen(ptr)+1]())
	{
		strcpy_s(mptr, strlen(ptr) + 1, ptr);
	}
	String(const String& rhs)
	{
		mptr = new char[strlen(rhs.mptr) + 1]();
		strcpy_s(mptr, strlen(rhs.mptr) + 1, rhs.mptr);
	}
	const String operator+(char* rhs)
	{
		char* tmp = new char[strlen(mptr) + strlen(rhs)+1]();
		strcpy_s(tmp, strlen(mptr) + 1, mptr);
		strcat(tmp, rhs);
		String str(tmp);
		delete[] tmp;
		return str;
	}
	const String operator+(const String& rhs)
	{
		char* tmp = new char[strlen(rhs.mptr) + strlen(mptr) + 1]();
		strcpy_s(tmp, strlen(mptr) + 1, mptr);
		strcat(tmp,rhs.mptr);
		String lhs(tmp);
		delete[] tmp;
		return lhs;
	}
	friend const String operator+(char*, const String&);
	bool operator<(const String& str)
	{
		return strcmp(mptr, str.mptr) < 0;
	}
	bool operator!=(const String& str)
	{
		return strcmp(mptr,str.mptr)!=0;
	}
	char& operator[](int index)//[]运算符重载函数
	{
		return mptr[index];
	}
	iterator begin()
	{
		return iterator(this,0);
	}
	iterator end()
	{
		return iterator(this, strlen(mptr));
	}

	friend std::ostream& operator<<(std::ostream&, const String&);
	friend std::ostream& operator>>(std::ostream&, const String&);
private:
	char* mptr;
};
char& Iterator::operator*()//特殊,this指针接收右操作数(平时都是左边)
//返回的是指向的元素本身,指向的是字符
{
	return (*pstr)[index];
	//pstr解引用,就会变成对象,即(*pstr).operator[](index)
}
const String operator+(char* str,const String& rhs)
{
	char* tmp = new char[strlen(str) + strlen(rhs.mptr) + 1]();
	strcpy_s(tmp, strlen(str) + 1,str);
	strcat(tmp, rhs.mptr);
	String lhs(tmp);
	delete[] tmp;
	return lhs;
}
std::ostream& operator<<(std::ostream& out, const String& str)
{
	out << str.mptr << " ";
	return out;
}

int main()
{
	std::string str1("hello");
	//std::string str2("world");

	//std::cout << str1[0] << std::endl; //str是对象,不是指针,所以要写[]运算符重载函数
	std::string::iterator it = str1.begin();//把it对象当作指针来使用
											//面向对象的指针:以对象的形式存在,但是做的却是指针的事
	while (it != str1.end())
	{
		std::cout << *it;//*it是对象的解引用,要实现一个解引用运算符重载函数
		it++;  //++就实现了getnext函数
	}
	//String str1("hello");
	//String str2 = str1 + " world";//除了运算符重载+,还有一个深拷贝(拷贝构造),将值赋给str2
	//String str3 = "hi " + str1;
	//String str4 = str1 + str2;

	//if (str1 < str2)
	//{
	//	std::cout << str1 << std::endl;
	//}
	std::cout << str2 << std::endl;
	std::cout << str3 << std::endl;

	//if (str3 != str4)
	//{
	//	std::cout << str4 << std::endl;
	//}
	return 0;
}

通过指针,指向对象。通过标识迭代位置。
在这里插入图片描述

6.String类的写时拷贝

class String
{
public:
	String(char* ptr)
	{
		mptr = new char[strlen(ptr) + 1 + 4]();//+4是计数器ref
		mptr += 4;//指向数据域
		strcpy_s(mptr, strlen(ptr) + 1, ptr);//把数据拷贝进去
		getRef() = 1;
	}
	String(const String& rhs)//浅拷贝
	{
		mptr = rhs.mptr;
		getRef()++;
	}
	String& operator=(const String& rhs)
	{
		if (this != &rhs)
		{
			--getRef();
			if (getRef() == 0)
			{
				delete[] (mptr - 4);
			}
			mptr = rhs.mptr;
			getRef()++;
		}
		return *this;
	}
	~String()
	{
		--getRef();
		if (getRef() == 0)
		{
			delete[] (mptr - 4);//避免内存释放,先释放堆内存
		}
		mptr = NULL;
	}
	char& operator[](int index) //深拷贝
	{
		if (getRef() > 1)
		{
			char* tmp = new char[strlen(mptr) + 1 + 4]();
			tmp += 4;
			strcpy_s(tmp, strlen(mptr) + 1, mptr);
			--getRef();
			mptr = tmp;
			getRef() = 1;
		}
		return mptr[index];
	}
private:
	int& getRef()//要修改并返回,因此类型用&,本身
	{
		return  *(int*)(mptr - 4);//把char*类型转成int*类型,然后解引用
	}
	char* mptr;
};
int main()
{
	String str1("hello");
	String str2(str1);
	String str3(str2);
	String str4("world");
	str2[0] = 'a';
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
str的本质就是指向字符串的
在这里插入图片描述
A是一个赋值操作,B是修改操作
在这里插入图片描述
在这里插入图片描述

7.写时拷贝的缺陷

/*
	设计点 : 
		operator[]
			深拷贝 
		知不知道使用者使用operator[]做修改操作还是访问操作?
		如果只是访问操作,采用深拷贝会造成内存浪费
*/
class String;
int main()
{
	String str1("hello");
	str1[0] = 'w';//修改  operator[]
	std::cout << str1[0] << std::endl;//访问 operator[],如果只是访问操作,采用深拷贝会造成内存浪费
	return 0;
}

在这里插入图片描述

8.内存自主管理机制

重载new和delete

/*
	重载new和delete
	void* malloc(size_t size);
	void free(void* ptr);
*/
/*
	new关键字 
		1.开辟内存	operator new 系统 允许重载 
		2.调用构造函数
	delete关键字
		1.调用析构函数
		2.释放内存
*/
/*  C语言中不允许重载,malloc和delete不能修改
	void* malloc(size_t);
	void free(void*);
*/
void* operator new(size_t size) 
{
	std::cout << "operator new!" << std::endl;
	return malloc(size);
} 
void operator delete(void* ptr)
{
	std::cout << "operator delete!" << std::endl;
	free(ptr);
}
int main()
{
	int* p = new int(10);
	*p = 20;
	delete p;
	return 0;
}

BSP:硬件资源(内存),由操作系统管理

在这里插入图片描述
在这里插入图片描述
内碎片:使用的空间小于开辟的空间,剩余的空间就是内碎片
在这里插入图片描述

9.内存池

池是什么意思? 
	资源的集合 
	池中申请,返还给池 
	资源的循环利用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include<iostream>

template<typename T>
class Queue;
const int QueueItem_Count = 10;
template<typename T>
class QueueItem
{
public:
	QueueItem(T val = T())
		:mdata(val), pnext(NULL)
	{}
	void* operator new(size_t size)
	{
		if (pool == NULL)
		{
			pool = (QueueItem<T>*)new char[size * QueueItem_Count];
			QueueItem<T>* pCur = pool;
			for (pCur; pCur < pool + QueueItem_Count - 1;
				pCur = pCur + 1)
			{
				pCur->pnext = pCur + 1;
			}
			pCur->pnext = NULL;
		}
		void* prt = pool;  //已分配的需要剔除,不带头结点的头删
		pool = pool->pnext;
		return prt;
	}
	void operator delete(void* ptr)
	{
		QueueItem<T>* pqptr = (QueueItem<T>*)ptr;
		pqptr->pnext = pool;
		pool = pqptr;
	}
private:
	template<typename T>
	friend class Queue;
	T mdata;
	QueueItem<T>* pnext;
	static QueueItem<T>* pool;
};
template<typename T>
QueueItem<T>* QueueItem<T>::pool = NULL;

template<typename T>
class Queue
{
public:
	Queue()
	{
		phead = ptail = new QueueItem<T>();
		/*
			1.operator new  
		*/
	}
	~Queue()
	{
		QueueItem<T>* pCur = phead;
		QueueItem<T>* pNext;
		while (pCur != NULL)
		{
			pNext = pCur->pnext;
			delete pCur;
			/*
				1.调用析构函数
				2.operator delete 
			*/
			pCur = pNext;
		}
		phead = NULL;
	}

	void push(T val)
	{
		QueueItem<T>* pnewitem = new QueueItem<T>(val);

		ptail->pnext = pnewitem;
		ptail = ptail->pnext;
	}
	bool empty()
	{
		return (phead == ptail) && (phead != NULL);
	}
	void pop()
	{
		if (empty())
		{
			return;
		}
		QueueItem<T>* pCur = phead->pnext;  //指向第一个节点
		phead->pnext = pCur->pnext;
		delete pCur;
	}
	T back()
	{
		if (empty())
		{
			throw std::exception("queu is empty!");
		}
		return ptail->mdata;
	}
	T front()
	{
		if (empty())
		{
			throw std::exception("queu is empty!");
		}
		return phead->pnext->mdata;
	}
private:
	QueueItem<T>* phead;
	QueueItem<T>* ptail;
};
int main()
{
	Queue<int> que;
	for (int i = 0; i < 5; i++)
	{
		que.push(i + 1);//  2 3 4 5
	}
	que.pop();
	auto qfront = que.front();
	auto qback = que.back();
	std::cout << "queue front: " << qfront << std::endl;
	std::cout << "queue back: " << qback << std::endl;
	return 0;
}

10.通用内存池

在这里插入图片描述

#include<iostream>
#include<string>
/*
	内存池  
*/
const int MEM_SIZE = 10;
template<typename T>
class MEM_Pool
{
public:
	MEM_Pool()
	{
		pool = NULL;
	}
	void* Alloc(rsize_t size)
	{
		if (pool == NULL)
		{
			pool = (Node*)new char[(size + 4) * MEM_SIZE]();
			Node* pCur = pool;
			for (pCur; pCur < pool + MEM_SIZE - 1; pCur = pCur + 1)
			{
				pCur->pnext = pCur + 1;
			}
			pCur->pnext = NULL;
		}
		void* rt = pool;
		pool = pool->pnext;
		return rt;
	}
	void Dealloc(void* ptr)
	{
		Node* pptr = (Node*)ptr;
		if (pptr == NULL)
		{
			return;
		}
		pptr->pnext = pool;
		pool = pptr;
	}
private:
	class Node
	{
	public:
		Node(T val)
			:mdata(val), pnext(NULL)
		{}
	public:
		T mdata;
		Node* pnext;
	};
	Node* pool;
};

class Student
{
public:
	Student(std::string name, std::string id, int age)
		:mname(name), mid(id), mage(age)
	{}
	void* operator new(size_t size)
	{
		return mm.Alloc(size);
	}
	void operator delete(void* ptr)
	{
		mm.Dealloc(ptr);
	}
private:
	std::string mname;
	std::string mid;
	int mage;
	static MEM_Pool<Student> mm;
};
MEM_Pool<Student> Student::mm;
/*
	operator
*/
class CGoods
{
public:
	CGoods(std::string name, float price, int amount)
		:mname(name), mprice(price), mamount(amount)
	{}

	void* operator new(size_t size)
	{
		return mm.Alloc(size);
	}
	void operator delete(void* ptr)
	{
		mm.Dealloc(ptr);
	}
private:
	std::string mname;
	float mprice;
	int mamount;
	static MEM_Pool<CGoods> mm;  //所有学生共用一个内存池
};
MEM_Pool<CGoods> CGoods::mm;

int main()
{
	Student* pstu1 = new Student("zhangsan", "001", 20);
	Student* pstu2 = new Student("lisi", "002", 22);

	delete pstu2;
	return 0;
}

11.智能指针

在这里插入图片描述

在这里插入图片描述
以前:
堆内存只有地址没有名称的,而我们的操作是基于对象名来操作内存单元的,因此将堆的所有权交给栈上有名称的变量来进行管理。
现在:
将堆的所有权交给栈上的一个对象。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<string>
template<typename T>

class SmartPtr
{
public:
	SmartPtr(T* ptr):mptr(ptr)
	{
		std::cout << "SmartPtr::SmartPtr" << std::endl;
	}
	~SmartPtr()
	{
		std::cout << "SmartPtr::~SmartPtr" << std::endl;
		delete mptr;
		mptr = NULL;
	}
	//特殊,this接收的是右操作数
	T& operator *()
	{
		return *mptr;
	}
	T* operator ->()
	{
		return mptr;
	}
private:
	T* mptr;
};
class Test
{
public:
	Test(int a)
		:ma(a)
	{}
	void Show()
	{
		std::cout << "ma:" << ma << std::endl;
	}
public:
	int ma;
};

int main()
{
/*
	以前用对象访问:
	int* p = new int;
	*p = 20;
*/

	
	Test* ptest = new Test(10);
	ptest->ma;
	ptest->Show();
	
	SmartPtr<int> sp(new int);
	*sp = 20;

	SmartPtr<Test> sp2 ( new Test(20));
	sp2->ma;
	sp2->Show();

	return 0;
}

11.重点内存池

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值