C + + self implementation String

Keywords: C C++

Mstring infrastructure

#ifndef MSTRING_H
#define MSTRING_H
#include<iostream>
using namespace std;

#define MSTRING_NUM_SIZE sizeof(int) / / reference count size
#define DEFEALT_LEN (10+MSTRING_NUM_SIZE)

class Mstring
{
public:
	Mstring(const char* str);
	Mstring(const Mstring& src);
	Mstring& operator=(const Mstring& src);
	~Mstring();
	void push_back(char c);//Tail insertion
	void pop_back();//Tail deletion
	char back()const;//Get the last element
	char front()const;//Get the first element 
	bool empty()const;
	int size()const;

	Mstring operator+(const Mstring& str)const;
	char& operator[](int pos);
	char operator[](int pos)const;

	friend ostream& operator<<(ostream& out, const Mstring& str);
	friend istream& operator>>(istream& in, Mstring& str);

private:

	bool full()const;
	void revert();


	char* _str;//The space requested on the heap is used to store data; Can I use shallow copy directly ----- how to increase the reference count
	int _len;//Total space size
	int _val_len;//Actual occupied space, actual data quantity
};




#endif // !MSTRING_H
#include"mstring.h"


Mstring::Mstring(const char* str = NULL)
{
	if (NULL == str)
	{
		_len = DEFEALT_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);
	_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);
	_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];
	}
	return *this;
}

Mstring::~Mstring()
{
	delete[]_str;
}

void Mstring::push_back(char c)//Tail insertion
{
	if (full())//Full sentence
	{
		revert();//If full, expand the capacity
	}
	_str[_val_len] = c;
	_val_len++;
}
void Mstring::pop_back()//Tail deletion
{
	if (empty())
	{
		return;
	}
	_val_len--;
}
char Mstring::back()const//Get the last element
{
	if (empty())
	{
		return 0;
	}
	return _str[_val_len - 1];
}
char Mstring::front()const//Get the first element 
{
	if (empty())
	{
		return 0;
	}
	return _str[0];
}
bool Mstring::empty()const
{
	return _val_len;
}

Mstring Mstring::operator+(const Mstring& str)const
{
	char* p;
	int len = _val_len + str._val_len + 1;
	p = new char[len];
	memset(p, 0, len);
	int i = 0;
	for(;i<_val_len;i++)
	{
		p[i] = _str[i];
	}
	for (int j = 0; j < str._val_len; j++, i++)
	{
		p[i] = str._str[j];
	}
	return p;//The return pointer is constructed directly as an object
}
char& Mstring::operator[](int pos)//The return value is a reference to ensure that it can be modified by the outside world
{
	return _str[pos];
}

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

bool Mstring::full()const
{
	return _val_len == _len - 1;
}

void Mstring::revert()
{
	_len = _len << 1;//Moving one bit to the left is equivalent to multiplying by 2

	char* p;
	p = new char[_len];
	memset(p, 0, _len);
	int i = 0;
	for (; i < _val_len; i++)
	{
		p[i] = _str[i];
	}
	delete[]_str;
	_str = p;
}

int Mstring::size()const
{
	return _val_len;
}

ostream& operator<<(ostream& out, const Mstring& str)
{
	int i = 0;
	for (; i < str._val_len; i++)
	{
		out << str._str[i];
	}
	out << endl;
	return out;
}

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

Realistic copy

	Mstring s1("xsy");
	Mstring s4 = s1;//Copy structure - deep copy
	cout << s1 << endl;
	cout << s4 << endl;

Purpose of realistic copy

The purpose of realistic copy is to improve the efficiency of code. In this example, both the copy structure and the overload of the assignment operator are deep copies. Finally, the memory is only read without modification, which wastes the space for re application. Therefore, the purpose of realistic copy is to replace the deep copy with the shallow copy without modification, just to make the object_ str points to the same block of memory. When reading, it can be read smoothly without wasting other space. Make a deep copy when the object needs to modify the data. This improves the efficiency of the code

But there is a problem: when the object is destructed, the shallow copy object will destruct the same memory space repeatedly, resulting in errors. Therefore, you need to use reference counting to avoid.

How do I increase the reference count?
Method 1: define a static variable. However, because different objects need to count with this variable, this method is not feasible.

Method 2: store the reference count in the first 4 bytes of each memory block.

#define MSTRING_NUM_SIZE sizeof(int) / / reference count size
#define DEFEALT_LEN (10+MSTRING_NUM_SIZE)

Mstring iterator

An iterator is a pointer to the data inside the container - essentially an object


Purpose of using iterators

There are many storage types (List,Map,Vector...) in C + +, each of which has its own unique access method. For so many data types, is there a general access method to make access efficient and simple? The existence of iterators is equivalent to shielding the unique access methods of different data structures, and using iterators achieves unified processing.

Output through iterator

Modify by iterator

Insert through iterator

Correct modification:

Delete by iterator

Notes on using iterators

1. After modifying container elements with iterators, you need to retrieve iterators again, because modifying will invalidate iterators
2. The use of iterators does not consider the problem of out of bounds, because there are begin() and end()
Equivalent to [), end() points to an invalid element
3. When dereferencing an iterator, you need to call the [] operator of Mstring class. Therefore, you need to implement char & operator * (); in mstring.cpp. When the compiler compiles, it will know where the [] operator is implemented. Otherwise, the code will report an error

Cross reference header file

There is also an error modification method: reference mstring.h in mstring_iterator.h
The reason for the error is: this will cause cross reference to the header file, and the compiler will expand the header file for precompiling. In this way, it will cause a circular expansion of the header file. An error will still be reported

Posted by FinalMjolnir on Sun, 28 Nov 2021 12:55:24 -0800