IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++:使用类来模拟 string(方法一) -> 正文阅读

[C++知识库]C++:使用类来模拟 string(方法一)

模拟string

基础代码:

class String
{
private:
	char* str;

public:
	// 构造函数
	String(const char* p = NULL) : str(NULL)
	{
		if (p != NULL)
		{
			str = new char[strlen(p) + 1];
			strcpy(str, p);
		}
		else
		{
			str = new char[1];
			*str = '\0';
		}
		cout << "Create String: " << this << endl;
	}
	//析构函数
	~String()
	{
		if (str != NULL)
		{
			delete[]str;
		}
		str = NULL;
		cout << "destroy String: " << this << endl;
	}

模拟输出(<<)

	ostream& operator<<(ostream& out) const
	{
		if (str != NULL)
		{
			out << str;
		}
		return out;
	}

这个函数是类的成员函数,有两个形参:实际上函数参数可以理解为:

ostream& operator<<(const String* const this, ostream& out);

为了避免使用友元函数,需要在类外在写一个输出函数

ostream& operator<<(ostream& out, const String& s)
{
	s << out;
	return out;
}

这样可以避免友元的使用:

int main(void)
{
	String s1("hello");

	cout << s1 << endl;

	return 0;
}

在这里插入图片描述

拷贝构造函数

	//拷贝构造
	String(const String& s)
	{
		str = new char[strlen(s.str) + 1];
		strcpy(str, s.str);
		
		cout << "Copy Create: " << this << endl;
	}
int main(void)
{
	String s1("hello");

	String s2(s1);

	return 0;
}

在这里插入图片描述

赋值运算符重载

	//赋值
	String& operator =(const String& s)
	{
		if (this != &s)
		{
			delete[] str;
			str = new char[strlen(s.str) + 1];
			strcpy(str, s.str);
		}

		cout << this << " operator= " << &s << endl;
		return *this;
	}

注意点:防止自赋值,防止内存泄漏,防止浅拷贝

int main(void)
{
	String s1("hello");
	String s2;

	s2 = s1;

	return 0;
}

在这里插入图片描述

加法运算符重载

因为返回时要构造一个对象,所以重载一个构造函数,作为私有成员。

private:
	char* str;

	String(char* p, int)
	{
		str = p;
	}

对象和对象相加

	//对象和对象相加
	String operator+(const String& s) const
	{
		char* p = new char[strlen(this->str) + strlen(s.str) + 1];
		strcpy(p, this->str);
		strcat(p, s.str);
		
		cout << "Object + Object" << endl;
		return String(p, 1);
	}
int main(void)
{
	String s1("hello");
	String s2("world");
	
	s1 = s1 + s2;

	return 0;
}

在这里插入图片描述

对象和字符串相加

	//对象和字符串相加
	String operator +(const char* s) const
	{
		char* p = new char[strlen(this->str) + strlen(s) + 1];
		strcpy(p, this->str);
		strcat(p, s);

		cout << "Object + char*" << endl;
		return String(p, 1);
	}
int main(void)
{
	String s1("hello");
	String s2;

	s2 = s1 + "world";

	return 0;
}

在这里插入图片描述

字符串和对象相加

可以借助上面写的函数,简单实现字符串与对象相加

//字符串和对象相加
String operator+(const char* p, const String& s)
{
	cout << "char* + Object" << endl;
	return String(p) + s;
}
int main(void)
{
	String s1("hello");
	String s2;

	s2 = "world" + s1;

	return 0;
}

在这里插入图片描述

移动构造函数

即实现资源的转移

	//移动构造
	String(String&& s)
	{
		cout << "move copy construct: " << this << endl;
		str = s.str;
		s.str = NULL;
	}
String fun()
{
	String s2("world");
	return s2;   // 不具名对象
}
int main(void)
{
	String s1;
	s1 = fun();

	return 0;
}

在程序执行到return s2; 时,就会调用移动构造函数,将 s2的资源转移,然后置为NULL。
在这里插入图片描述
在这里插入图片描述

运行结果:
在这里插入图片描述

移动赋值函数

	// 移动赋值
	String& operator=(String&& s)
	{
		if (this != &s)
		{
			s.str = Release(s.str);
		}
		cout << this << " move operator=: " << &s << endl;
		return *this;
	}
	char* Release(char* p)
	{
		char* old = str;
		str = p;
		return old;
	}
String fun()
{
	String s2("world");
	return s2;   // 不具名对象
}
int main(void)
{
	String s1;
	s1 = fun();

	return 0;
}

详解

在程序运行到return s2; 时移动构造出一个将亡值,然后析构 s2;
在这里插入图片描述

fun()结束时返回调用点,调用移动赋值函数

在这里插入图片描述

调用完 Release() 实现资源的交换,移动赋值完成。

在这里插入图片描述

运行结果:
由于运行了几次,地址发生了变化,不影响查看。。

在这里插入图片描述

图示

  1. 移动构造将亡值,指向 s2申请的空间,析构 s2
  2. 拿将亡值移动赋值 s1
  3. Release()函数实现资源的交换,使 s1指向原 s2申请的空间,将亡值指向原 s1申请的空间,函数结束,将亡值析构,s1成功拿到 原s2的资源。
    在这里插入图片描述

完整代码

#include<iostream>
#include<cstdlib>
#include<string.h>
using namespace std;

class String
{
private:
	char* str;

	String(char* p, int)
	{
		str = p;
	}
public:
	String(const char* p = NULL) : str(NULL)
	{
		if (p != NULL)
		{
			str = new char[strlen(p) + 1];
			strcpy(str, p);
		}
		else
		{
			str = new char[1];
			*str = '\0';
		}
		cout << "Create String: " << this << endl;
	}
	~String()
	{
		if (str != NULL)
		{
			delete[]str;
		}
		str = NULL;
		cout << "destroy String: " << this << endl;
	}

	//类的成员函数,带有两个参数
	//ostream& operator<<(const String* const this, ostream& out);
	ostream& operator<<(ostream& out) const
	{
		if (str != NULL)
		{
			out << str;
		}
		return out;
	}
	// s1 << cout;
	// s1.operator << (cout);
	// operator << (&s1.cout);

	//拷贝构造
	String(const String& s)
	{
		str = new char[strlen(s.str) + 1];
		strcpy(str, s.str);
		
		cout << "Copy Create: " << this << endl;
	}

	//赋值
	String& operator =(const String& s)
	{
		if (this != &s)
		{
			delete[] str;
			str = new char[strlen(s.str) + 1];
			strcpy(str, s.str);
		}

		cout << this << " operator= " << &s << endl;
		return *this;
	}

	//对象和对象相加
	String operator+(const String& s) const
	{
		char* p = new char[strlen(this->str) + strlen(s.str) + 1];
		strcpy(p, this->str);
		strcat(p, s.str);

		cout << "Object + Object" << endl;
		return String(p, 1);
	}

	//对象和字符串相加
	String operator +(const char* s) const
	{
		char* p = new char[strlen(this->str) + strlen(s) + 1];
		strcpy(p, this->str);
		strcat(p, s);

		cout << "Object + char*" << endl;
		return String(p, 1);
	}

	//移动构造
	String(String&& s)
	{
		cout << "move copy construct: " << this << endl;
		str = s.str;
		s.str = NULL;
	}

	// 移动赋值
	String& operator=(String&& s)
	{
		if (this != &s)
		{
			s.str = Release(s.str);
		}
		cout << this << " move operator=: " << &s << endl;
		return *this;
	}
	char* Release(char* p)
	{
		char* old = str;
		str = p;
		return old;
	}
};

ostream& operator<<(ostream& out, const String& s)
{
	s << out;
	//s.operator<<(out);
	//operator << (&s, out);
	return out;
}

//字符串和对象相加
String operator+(const char* p, const String& s)
{
	cout << "char* + Object" << endl;
	return String(p) + s;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:57:07  更:2022-03-11 21:58:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:39:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码