c++ || string类

本文介绍了C++中mstring类的基础知识,包括将其定义为常函数以确保不可变性,以及实现写时拷贝策略。写时拷贝通过在多个对象共享内存时只允许读取,当需要修改时才复制内存,从而减少内存消耗和提高效率。同时,文章提及了引用计数在实现中的应用,用于决定何时可以析构对象。

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


通过对string类的实现来熟悉c++库中string都有哪些方法

mstring 基础类

对所有已经确定好在之后是不会改变的函数都定义成为常函数
size back front empty

#ifndef MSTRING_H
#define MSTRING_H
#include<iostream>
using namespace std;
#define DEFAULT_LEN 10
class Mstring 
{
public:
	Mstring(const char* str = NULL);  //带参构造函数
	Mstring(const Mstring& src);//拷贝构造函数
	Mstring& operator=(const Mstring& src); //等号运算符重载
	~Mstring();//析构函数

	void push_back(char c); //尾插
	void pop_back();        //弹出最后一个元素
	char back()const;       //返回最后一个元素
	char front()const;      //返回第一个元素
	bool empty()const;      //判空
	int size()const;        //字符串大小

	Mstring operator+(const Mstring& str); //加号运算符重载 
	char& operator[](int pos); //中括号运算符重载
	char operator[](int pos)const; //中括号运算符重载 常函数
	
	//写在类外的函数必须要加友元
	friend ostream& operator<<(ostream& out, const Mstring& str);  //类外实现的输出函数 形参字符串要加上const 不能被修改
	friend istream& operator>>(istream& in, Mstring& str);  //类外实现的输入函数 输入的字符串一定不是常量

private:
	//对外界不提供 
	bool full()const;  //判满
	void revert();//扩容

	char* _str;
	int _len;   //当前空间总长度
	int _val_len;//已经占用的长度 数据长度
};

#endif // !MSTRING_H

#include"mstring.h"
Mstring::Mstring(const char* str)
{
	if (NULL == str)
	{
		_len = DEFAULT_LEN;
		_val_len = 0;
		_str = new char[_len];
		memset(_str, 0, _len);
		return;
	}

	_val_len = strlen(str);
	_len = _val_len + 1;
	_str = new char[_len];
	memset(_str, 0, _len);

	for (int i = 0;i < _val_len; i++)
	{
		_str[i] = str[i];
	}
}
Mstring::Mstring(const Mstring& src)
{

	_val_len = strlen(src._str);//_val_len = src._val_len
	_len = _val_len + 1;
	_str = new char[_len];
	memset(_str, 0, _len);

	for (int i = 0; i < _val_len; i++)
	{
		_str[i] = src._str[i];
	}
}
Mstring& Mstring::operator=(const Mstring& src)
{
	//防止自赋值
	if (&src == this)
	{
		return *this;
	}
	//删除所有原来的数据
	delete[]_str;
	//赋值 防止浅拷贝
	_val_len = strlen(src._str);//_val_len = src._val_len
	_len = _val_len + 1;
	_str = new char[_len];
	memset(_str, 0, _len);

	for (int i = 0; i < _val_len; i++)
	{
		_str[i] = src._str[i];
	}
}
Mstring::~Mstring()
{
	delete[]_str;
}

void Mstring::push_back(char c)
{
	if (full())
	{
		revert();
	}

	_str[_val_len] = c;  //存储的实际数据长度就是最后一个要插入的元素的位置
	_val_len++;
}
void Mstring::pop_back()
{
	if (empty())
	{
		return;
	}
	_val_len--;
}
char Mstring::back()const
{
	if (empty())
	{
		return 0;
	}

	return _str[_val_len - 1];
}
char Mstring::front()const
{
	if (empty())
	{
		return 0;
	}

	return _str[0];
}
bool Mstring::empty()const
{
	return _val_len == 0;
}


Mstring Mstring::operator+(const Mstring& str)
{
	char* p;
	int len = _val_len + str._val_len;

	p = new char[len];
	memset(p, 0, len);

	//进行数据的拷贝 将两个字符串的数据拼接起来
	//先加自己的数据 在从后面加上第二个字符串的数据
	int i = 0;  //i要声明在外面 下一个循环也要使用
	for (; i < _val_len; i++)
	{
		p[i] = _str[i];
	}
	for (int j = 0; j < str._val_len; j++)
	{
		p[i] = str._str[j];
	}

	return p;
}

char& Mstring::operator[](int pos)
{//返回引用 便于在外界进行修改
	return _str[pos];
}

char Mstring::operator[](int pos)const
{
	return _str[pos];
}
int Mstring::size()const
{
	return _val_len;
}

bool Mstring::full()const  //判满
{
	return _val_len == _len-1;
	// _len-1  减去'\0'的位置
}
void Mstring::revert()//扩容
{
	_len = _len << 1; //向左挪一位 相当于乘以2
	char* p = new char[_len];

	memset(p, 0, _len);
	//将原来的数据拷贝过来
	for (int i = 0; i < _val_len; i++)
	{
		p[i] = _str[i];
	}
	//防止内存泄露 删除原来的str
	delete[]_str;
	//重新指向扩容好的数据
	_str = p;
}

ostream& operator<<(ostream& out, const Mstring& str)
{
	for (int i = 0; i < str.size(); i++)
	{
		cout << str[i];//重载的中括号 常函数的[]
	}
	cout << endl;
	return out;
}

istream& operator>>(istream& in,  Mstring& str)
{
	char tmp[1024];
	in >> tmp;
	str = tmp;
	return in;
}

mstring 写时拷贝

当多个对象同时拥有同一块内存时,每个对象都只有读取的权限
如果有某个对象需要改动这一块内存的时候,就给该对象拷贝出一份独有的内存
不能修改共有的这块内存

  • 优点:
  1. 减少内存的消耗 :拷贝构造时新产生的对象如果从开始到死亡都不会对原来的对象进行修改 则就可以直接指向原来对象的空间地址,节省需要新开辟出的空间
  2. 节省时间:新对象不用new的这一步 则在最后就也不需要delete这一步,节省了时间

调用引用计数,判断该对象是否能对进行析构
引用计数放的位置:在_str里面多开辟四个字节用来存放引用计数
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值