欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++模擬實(shí)現(xiàn)string的詳細(xì)過程

 更新時(shí)間:2024年08月11日 09:33:10   作者:JhonKI  
在?C++?編程中,字符串的處理是一項(xiàng)常見且重要的任務(wù),標(biāo)準(zhǔn)庫中的?string?類為我們提供了便捷、高效的字符串操作方法,模擬實(shí)現(xiàn)?string?類?的背景源于對(duì)?C++?底層原理的探索欲望,所以本文給大家介紹了C++模擬實(shí)現(xiàn)string的詳細(xì)過程,需要的朋友可以參考下

一、前言

在 C++ 編程中,字符串的處理是一項(xiàng)常見且重要的任務(wù)。標(biāo)準(zhǔn)庫中的 string 類為我們提供了便捷、高效的字符串操作方法。然而,深入理解其內(nèi)部實(shí)現(xiàn)機(jī)制對(duì)于提高編程技能和優(yōu)化代碼性能具有重要意義。

模擬實(shí)現(xiàn) string 類 的背景源于對(duì) C++ 底層原理的探索欲望。通過親手模擬實(shí)現(xiàn),我們能夠更清晰地理解字符串的存儲(chǔ)、管理和操作方式。

其重要性體現(xiàn)在多個(gè)方面。首先,有助于掌握內(nèi)存管理的細(xì)節(jié),如動(dòng)態(tài)分配、擴(kuò)容和釋放,避免內(nèi)存泄漏和提高資源利用效率。其次,能夠深入理解字符串的各種操作,如拷貝構(gòu)造、賦值、插入、刪除等,從而在實(shí)際編程中更加準(zhǔn)確和高效地運(yùn)用這些操作。此外,模擬實(shí)現(xiàn)過程培養(yǎng)了我們解決復(fù)雜問題的能力,提升了對(duì) C++ 語言特性的掌握程度。

總之,模擬實(shí)現(xiàn) string 類 不僅是對(duì)知識(shí)的深入挖掘,更是為了在實(shí)際編程中能夠更加得心應(yīng)手地處理字符串相關(guān)的任務(wù),編寫更加健壯和高效的代碼。

二、準(zhǔn)備工作

2.1 涵蓋必要的頭文件與命名空間

在對(duì) string 類進(jìn)行模擬實(shí)現(xiàn)時(shí),我們必須包含一些不可或缺的頭文件,例如 <iostream> 用于執(zhí)行輸入輸出操作,<cstring> 用于和字符串相關(guān)的函數(shù),諸如 strlen 、 strcpy 等。與此同時(shí),或許還需運(yùn)用命名空間,例如 using namespace std; ,從而更便捷地使用標(biāo)準(zhǔn)庫中的函數(shù)與對(duì)象。

2.2 簡述模擬實(shí)現(xiàn) string 所需的基礎(chǔ)概念和知識(shí)

模擬實(shí)現(xiàn) string 類需要熟稔一些關(guān)鍵的概念與知識(shí)。

首先是動(dòng)態(tài)內(nèi)存的管理,鑒于 string 的長度具備可變性,需要在運(yùn)行期間動(dòng)態(tài)地進(jìn)行內(nèi)存的分配與釋放,以存儲(chǔ)字符串的內(nèi)容。這牽涉到 new 和 delete 操作符的使用。

其次,要領(lǐng)會(huì)指針的操作,憑借指針來管理動(dòng)態(tài)分配的內(nèi)存。

還需熟知字符串的基本操作,像是字符串的拷貝、拼接、查找、插入、刪除等等。對(duì)于字符編碼和字符處理方面的知識(shí)也應(yīng)當(dāng)有所知曉,以保障字符串的處理準(zhǔn)確無誤。

此外,掌控構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符的重載也是至關(guān)重要的,以此確保對(duì)象能夠正確地創(chuàng)建、銷毀和復(fù)制。同時(shí),對(duì)于異常處理也應(yīng)當(dāng)具備一定的認(rèn)知,用以處理可能出現(xiàn)的諸如內(nèi)存分配失敗等異常狀況。

三、成員變量

  1. char _str*
    char* _str 是一個(gè)指針,用于動(dòng)態(tài)地存儲(chǔ)字符串的數(shù)據(jù)。在模擬實(shí)現(xiàn) string 類的過程中,它承擔(dān)著核心的角色。通過動(dòng)態(tài)分配內(nèi)存,_str 能夠根據(jù)字符串內(nèi)容的長度靈活地調(diào)整存儲(chǔ)空間,從而有效地管理字符串?dāng)?shù)據(jù)。在進(jìn)行字符串的操作,如拷貝、修改、插入或刪除時(shí),都是基于 _str 所指向的內(nèi)存區(qū)域進(jìn)行的。

  2. size_t _capacity
    size_t _capacity 用于記錄字符串的容量,即當(dāng)前為存儲(chǔ)字符串所分配的內(nèi)存空間大小。它在字符串的擴(kuò)容操作中起著關(guān)鍵作用。當(dāng)字符串的長度即將超過當(dāng)前分配的容量時(shí),需要根據(jù)一定的策略(如倍增或按照特定比例增加)來重新分配更大的內(nèi)存空間,并更新 _capacity 的值,以確保有足夠的空間容納不斷增長的字符串。

  3. size_t _size
    size_t _size 表示字符串的有效長度,即實(shí)際存儲(chǔ)的字符數(shù)量。它與 _capacity 不同,_capacity 關(guān)注的是內(nèi)存空間,而 _size 關(guān)注的是字符串中實(shí)際包含的有效字符數(shù)。在進(jìn)行字符串的操作,如插入、刪除字符時(shí),需要根據(jù) _size 來確定操作的位置和范圍,以保證字符串的完整性和正確性。

四、默認(rèn)成員函數(shù)

4.1 構(gòu)造函數(shù)

// 短小頻繁調(diào)用的函數(shù),可以直接定義到類里面,默認(rèn)是inline
		string(const char* str = "")
		{
			_size = strlen(str);
			// _capacity不包含\0
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

上述構(gòu)造函數(shù)實(shí)現(xiàn)了帶缺省參數(shù)的功能。若傳入的字符串為空指針或空字符串,會(huì)進(jìn)行相應(yīng)的處理,為字符串分配適當(dāng)?shù)膬?nèi)存空間,并初始化_size_capacity

4.2 析構(gòu)函數(shù)

析構(gòu)函數(shù)用于釋放構(gòu)造函數(shù)中動(dòng)態(tài)分配的內(nèi)存,并將相關(guān)的成員變量重置為初始狀態(tài),以避免內(nèi)存泄漏和資源浪費(fèi)。

~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

4.3 拷貝構(gòu)造函數(shù)

在傳統(tǒng)的拷貝構(gòu)造函數(shù)中,首先計(jì)算源字符串的長度。然后,為新字符串分配足夠的內(nèi)存空間,并通過strcpy函數(shù)將源字符串的內(nèi)容復(fù)制到新分配的空間中。同時(shí),正確設(shè)置_size_capacity的值,以反映新字符串的長度和容量。

// 深拷貝問題
		
		string(const string& s)
		{
			_str = new char[s._capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}

4.4 拷貝構(gòu)造函數(shù)(臨時(shí)變量)

在現(xiàn)代的實(shí)現(xiàn)方式中,首先將_str初始化為nullptr。然后創(chuàng)建一個(gè)臨時(shí)對(duì)象tmp,其構(gòu)造過程會(huì)完成對(duì)源字符串的復(fù)制。接著,通過交換函數(shù)swap將臨時(shí)對(duì)象tmp的_str與當(dāng)前對(duì)象的_str進(jìn)行交換,從而實(shí)現(xiàn)深拷貝。同時(shí),也要確保_size和_capacity的值得到正確更新。

void swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

string(const string& s)
{
	string tmp(s._str);
	swap(tmp);
}

這種現(xiàn)代方式避免了直接的內(nèi)存分配和復(fù)制操作,通過巧妙地利用臨時(shí)對(duì)象和交換,提高了代碼的簡潔性和效率。

五、賦值運(yùn)算符重載

5.1 傳統(tǒng)方式處理空間分配和字符串復(fù)制

在傳統(tǒng)的賦值運(yùn)算符重載中,首先檢查當(dāng)前對(duì)象是否與傳入的對(duì)象不同。若不同,則先釋放當(dāng)前對(duì)象所占用的內(nèi)存。然后計(jì)算傳入對(duì)象字符串的長度,為新字符串分配足夠的內(nèi)存空間,并通過strcpy函數(shù)復(fù)制字符串內(nèi)容。同時(shí),正確設(shè)置_size和_capacity的值。

string& operator=(const string& s)
		{
			if (this != &s)
			{
				delete[] _str;

				_str = new char[s._capacity + 1];
				strcpy(_str, s._str);
				_size = s._size;
				_capacity = s._capacity;
			}

			return *this;
		}

5.2 現(xiàn)代方式通過交換實(shí)現(xiàn)賦值

string& operator=(string tmp)
{
	swap(tmp);
	return *this;
}

在現(xiàn)代的賦值實(shí)現(xiàn)方式中,首先創(chuàng)建一個(gè)傳入對(duì)象的副本other。然后通過交換函數(shù)swap交換當(dāng)前對(duì)象和副本對(duì)象的_str指針。接著,直接將副本對(duì)象的_size_capacity值賦給當(dāng)前對(duì)象。這種方式避免了直接的內(nèi)存分配和復(fù)制操作,提高了賦值的效率。

六、容量相關(guān)操作接口

6.1 size()

size() 函數(shù)用于返回字符串的有效長度,即實(shí)際存儲(chǔ)的字符數(shù)量。它不包括字符串末尾的空字符 '\0' 。在使用時(shí),直接調(diào)用 string 對(duì)象.size() 即可獲取字符串的有效長度。
例如:

size_t size() const{ return _size; }

在 size_t size() const { return _size; } 這段代碼中,const 關(guān)鍵字具有以下重要作用:

  1. 保證成員函數(shù)不修改類的成員變量:
    這意味著在這個(gè) size() 函數(shù)內(nèi)部,不能對(duì)類中的任何成員變量進(jìn)行修改操作。
    例如,如果類中有其他成員變量,如 int count; ,在這個(gè) size() 函數(shù)中就不能執(zhí)行類似于 count++; 這樣的修改操作。
  2. 使函數(shù)可以用于常量對(duì)象:
    當(dāng)有一個(gè)常量對(duì)象時(shí),只能調(diào)用其 const 成員函數(shù)。
    例如,如果有 const MyClass obj; ,那么只能通過 obj.size(); 來獲取大小,而不能調(diào)用可能修改對(duì)象狀態(tài)的非 const 成員函數(shù)。
  3. 增強(qiáng)程序的可讀性和可維護(hù)性:
    當(dāng)看到 const 修飾的成員函數(shù),開發(fā)者能立即明白該函數(shù)不會(huì)修改對(duì)象的狀態(tài)。

6.2 capacity()

capacity() 函數(shù)返回字符串當(dāng)前分配的內(nèi)存空間大小,即容量。它反映了為存儲(chǔ)字符串所預(yù)留的內(nèi)存空間。
例如:

size_t capacity() const{ return _capacity; }

6.3 reserve()

reserve() 函數(shù)用于調(diào)整字符串的容量。當(dāng)我們預(yù)計(jì)字符串可能會(huì)增長到一定規(guī)模時(shí),可以提前使用reserve()函數(shù)為其預(yù)留足夠的內(nèi)存空間,以減少后續(xù)頻繁的內(nèi)存重新分配操作,提高性能。

	void string::reserve(size_t n)
	{
		//	不能用realloc,必須匹配使用
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}

七、修改相關(guān)操作接口

7.1 push_back()在字符串末尾追加字符。

push_back() 函數(shù)用于在字符串的末尾追加一個(gè)字符。它能夠方便地?cái)U(kuò)展字符串的內(nèi)容。

	void string::push_back(char ch)
	{
		if (_size == _capacity)
			reserve(_capacity == 0 ? 4 : _capacity * 2);

		_str[_size] = ch;
		++_size;
		_str[_size] = '\0';
	}

例如:

string str = "Hello";
str.push_back('!');
cout << str << endl;  // 輸出:Hello!

在這個(gè)例子中,通過 push_back('!')操作,將感嘆號(hào)字符添加到了字符串 str 的末尾。

7.2 append()在字符串末尾追加字符串。

append() 函數(shù)可以在字符串的末尾追加一個(gè)字符串。其使用方式多樣,能滿足不同的需求。

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			//	大于2倍,要多少給多少,小于2倍按2倍擴(kuò)
			reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
		}
		strcpy(_str + _size, str);
		_size += len;
	}

例如:

string s1 = "Hello";
string s2 = " World";
s1.append(s2);
cout << s1 << endl;  // 輸出:Hello World

7.3 insert()在指定位置插入字符或字符串。

insert() 函數(shù)能夠在指定的位置插入字符或字符串。比如:

	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
		}
		size_t end = _size + len;
		while (end - len + 1 > pos)
		{
			_str[end] = _str[end - len];
			--end;
		}
		for (size_t i = 0; i < len; i++)
		{
			_str[pos + i] = str[i];
		}
		_size += len;
	}

還可以插入單個(gè)字符:

	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);

		if (_size == _capacity)
			reserve(_capacity == 0 ? 4 : _capacity * 2);
+
		//	挪動(dòng)數(shù)據(jù)
		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}

		_str[pos] = ch;
		_size++;
	}

八、非成員函數(shù)

8.1 流插入運(yùn)算符重載 (<<)

	ostream& operator<<(ostream& out, const string& s)	{
		for (auto ch : s)
			out << ch;
		return out;
	}

上述重載函數(shù)使得可以使用 << 運(yùn)算符將自定義的 String 對(duì)象輸出到標(biāo)準(zhǔn)輸出流中。它直接將 String 對(duì)象內(nèi)部存儲(chǔ)的字符串?dāng)?shù)據(jù)輸出。

8.2 流提取運(yùn)算符重載 (>>)

stream& operator>>(istream& in, string& s) {
		s.clear();

		const int  N = 256;
		char buff[N];

		int i = 0;

		char ch;
		ch = in.get();
		while (ch != ' ' && ch != '\n') {
			buff[i++] = ch;
			if (i == N - 1)
			{
				buff[i] = '\0';
				s += buff;

				i = 0;
			}

			ch = in.get();// 獲取下一個(gè)字符
		}
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}

此重載函數(shù)實(shí)現(xiàn)了從輸入流中讀取數(shù)據(jù)到 String 對(duì)象的功能。首先,使用一個(gè)臨時(shí)緩沖區(qū)讀取輸入數(shù)據(jù),然后將其轉(zhuǎn)換為 String 對(duì)象并賦值給傳入的 String 引用。

整體代碼

string.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once

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

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str + _size;
		}

		/*string()
			:_str(new char[1]{'\0'})
			,_size(0)
			,_capacity(0)
		{}*/

		// 短小頻繁調(diào)用的函數(shù),可以直接定義到類里面,默認(rèn)是inline
		string(const char* str = "")
		{
			_size = strlen(str);
			// _capacity不包含\0
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		// 深拷貝問題
		// 
		// s2(s1)
		string(const string& s)
		{
			_str = new char[s._capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}

		// s2 = s1
		// s1 = s1
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				delete[] _str;

				_str = new char[s._capacity + 1];
				strcpy(_str, s._str);
				_size = s._size;
				_capacity = s._capacity;
			}

			return *this;
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		const char* c_str() const
		{
			return _str;
		}

		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}

		size_t size() const
		{
			return _size;
		}

		size_t capacity() const
		{
			return _capacity;
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);

			return _str[pos];
		}

		const char& operator[](size_t pos) const
		{
			assert(pos < _size);

			return _str[pos];
		}

		void reserve(size_t n);
		void push_back(char ch);
		void append(const char* str);
		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos, size_t len = npos);

		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);
		string substr(size_t pos = 0, size_t len = npos);
	private:
		//char _buff[16];
		char* _str;
		size_t _size;
		size_t _capacity;

		//static const size_t npos = -1;
		static const size_t npos;

		/*static const int N = 10;
		int buff[N];*/
	};

	bool operator<(const string& s1, const string& s2);
	bool operator<=(const string& s1, const string& s2);
	bool operator>(const string& s1, const string& s2);
	bool operator>=(const string& s1, const string& s2);
	bool operator==(const string& s1, const string& s2);
	bool operator!=(const string& s1, const string& s2);

	ostream& operator<<(ostream& out, const string& s);
	istream& operator>>(istream& in, string& s);
}

string.cpp

#include"string.h"

namespace bit
{
	const size_t string::npos = -1;


	//	保留 + 擴(kuò)容
	void string::reserve(size_t n)
	{
		//	不能用realloc,必須匹配使用
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}


	void string::push_back(char ch)
	{
		if (_size == _capacity)
			reserve(_capacity == 0 ? 4 : _capacity * 2);

		_str[_size] = ch;
		++_size;
		_str[_size] = '\0';
	}

	//不能按2倍擴(kuò)容
	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			//	大于2倍,要多少給多少,小于2倍按2倍擴(kuò)
			reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
		}
		strcpy(_str + _size, str);
		_size += len;
	}

	string& string::operator+=(char ch)
	{
		push_back(ch);
		return *this;
	}
	
	string&string:: operator+=(const char* str)
	{
		append(str);
		return *this;
	}

	//	插入單個(gè)字符
	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);

		if (_size == _capacity)
			reserve(_capacity == 0 ? 4 : _capacity * 2);

		//	挪動(dòng)數(shù)據(jù)
		//int end = _size;
		//while (end >= (int)pos)//	不強(qiáng)轉(zhuǎn)會(huì)整形提升,導(dǎo)致pos為0時(shí)出錯(cuò)
		//{
		//	if (end == 0)
		//	{
		//		int i = 0;
		//	}
		//	_str[end + 1] = _str[end];
		//	--end;
		//}

		//	挪動(dòng)數(shù)據(jù)
		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}

		_str[pos] = ch;
		_size++;
	}

	//	插入字符串

	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
		}
		size_t end = _size + len;
		while (end - len + 1 > pos)
		{
			_str[end] = _str[end - len];
			--end;
		}
		for (size_t i = 0; i < len; i++)
		{
			_str[pos + i] = str[i];
		}
		_size += len;
	}


	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len > _size - pos)
		{
			_str[pos] = '\0';
			_size = pos;
		}

		else
		{
			for (size_t i = 0; i <= _size - pos - len; i++)
			{
				_str[pos + i] = _str[pos + i + len];
			}
			_size -= len;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = pos; i < _size ;i++)
		{
			if (_str[i] == ch)
				return i;
		}
		return npos;
	}

	size_t string::find(const char* str, size_t pos)
	{
		assert(pos < _size);

		const char* ptr = strstr(_str + pos, str);
		if (ptr != nullptr)
		{
			return ptr - _str;
		}
		else
			return npos;
	}

	//	substr 函數(shù)用于從一個(gè)字符串中提取子字符串
	string string::substr(size_t pos, size_t len)
	{
		assert(pos < _size);

		// len大于剩余字符長度,更新一下len
		if (len > _size - pos)
		{
			len = _size - pos;
		}

		string sub;
		sub.reserve(len);
		for (size_t i = 0; i < len; i++)
		{
			sub += _str[pos + i];
		}

		return sub;
	}

	//	字符串都是按ASCLL碼比較的
	bool operator<(const string& s1, const string& s2) {
		return strcmp(s1.c_str(), s2.c_str()) < 0;
	}
	bool operator<=(const string& s1, const string& s2) {
		return !(strcmp(s1.c_str(), s2.c_str()) > 0);
	}
	bool operator>(const string& s1, const string& s2) {
		return strcmp(s1.c_str(), s2.c_str()) > 0;
	}
	bool operator>=(const string& s1, const string& s2) {
		return !(strcmp(s1.c_str(), s2.c_str()) < 0);
	}
	bool operator==(const string& s1, const string& s2) {
		return strcmp(s1.c_str(), s2.c_str()) == 0;
	}
	bool operator!=(const string& s1, const string& s2) {
		return !(strcmp(s1.c_str(), s2.c_str()) > 0);
	}


	// 必須為全局,但不一定要為友元
	// 輸出流
	ostream& operator<<(ostream& out, const string& s)	{
		for (auto ch : s)
			out << ch;
		return out;
	}
	// 輸入流
	istream& operator>>(istream& in, string& s) {
		s.clear();

		const int  N = 256;
		char buff[N];

		int i = 0;

		char ch;
		ch = in.get();
		while (ch != ' ' && ch != '\n') {
			buff[i++] = ch;
			if (i == N - 1)
			{
				buff[i] = '\0';
				s += buff;

				i = 0;
			}

			ch = in.get();// 獲取下一個(gè)字符
		}
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}


	void test_string1()
	{
		string s1;
		string s2("hello world");
		cout << s1.c_str() << endl;
		cout << s2.c_str() << endl;
	
		for (size_t i = 0; i < s2.size(); i++)
		{
			s2[i] += 2;
		}
		cout << s2.c_str() << endl;

		//	范圍for的本質(zhì)就是迭代器
		for (auto e : s2)
		{
			cout << e << " ";
		}
		cout << endl;

		string::iterator it = s2.begin();
		while (it != s2.end())
		{
			cout << *it << " ";
			++it;
		}
	}




	void test_string2()
	{
		string s1("hello world");

		s1 += "  xxx";
		s1.append("  %%%");
		cout << s1.c_str() << endl;

		s1.insert(5, '^');
		cout << s1.c_str() << endl;

		s1.insert(5, " &&& ");
		cout << s1.c_str() << endl;

 		s1.erase(1);
		cout << s1.c_str() << endl;

	}


	void test_string3()
	{
		string s1("hello world");
		
		string s2 = s1.substr(0, 3);
		cout << s2.c_str() << endl;

		string copy(s1);
		cout << copy.c_str() << endl;

		string s3 = s1;
		cout << s3.c_str() << endl;

		char str[5];
		cin >> s1;
		cout << s1 << endl;
		cin >> s1 >> s2 >> str;
		cout << s1 << s2 <<str;
	}

	void test_string4()
	{
		std::string s1("11");
		std::string s2(s1);// 深拷貝
		printf("%p\n", s1.c_str());
		printf("%p\n", s2.c_str());

		cout << sizeof(s1) << endl;
		cout << sizeof(s2) << endl;
	}
}

總結(jié)

在模擬實(shí)現(xiàn) string 類的過程中,我們涉及了眾多的要點(diǎn)和需要特別注意的事項(xiàng)。
首先,對(duì)于成員變量的管理至關(guān)重要。char* _str 用于動(dòng)態(tài)存儲(chǔ)字符串?dāng)?shù)據(jù),其內(nèi)存的分配和釋放要精確控制,以避免內(nèi)存泄漏和錯(cuò)誤訪問。size_t _capacity 和 size_t _size 分別用于記錄容量和有效長度,它們的正確更新和使用影響著字符串的存儲(chǔ)和操作效率。
在函數(shù)實(shí)現(xiàn)方面,構(gòu)造函數(shù)要處理好空字符串和正常字符串的初始化。析構(gòu)函數(shù)務(wù)必釋放動(dòng)態(tài)分配的內(nèi)存??截悩?gòu)造函數(shù)和賦值運(yùn)算符重載需要確保深拷貝,避免淺拷貝導(dǎo)致的問題。

容量相關(guān)操作接口,如 reserve() 和 resize() ,要理解其對(duì)內(nèi)存和字符串長度的影響,以及不同實(shí)現(xiàn)方式的性能差異。

修改相關(guān)操作接口,如 push_back()、append()、insert() 和 erase() ,需要注意操作的邊界情況和對(duì)字符串狀態(tài)的更新。

遍歷訪問相關(guān)接口,迭代器的實(shí)現(xiàn)要保證操作符重載的正確性和高效性,operator[] 要進(jìn)行有效的索引檢查。

非成員函數(shù)中的流插入和流提取運(yùn)算符重載,要保證數(shù)據(jù)的正確傳輸和對(duì)象的正確賦值。

總之,模擬實(shí)現(xiàn) string 類需要對(duì) C++ 的內(nèi)存管理、指針操作、函數(shù)重載等知識(shí)有深入的理解和熟練的運(yùn)用,同時(shí)要注重代碼的效率、安全性和可維護(hù)性。只有這樣,才能實(shí)現(xiàn)一個(gè)功能完善、性能優(yōu)良的 string 類模擬。

以上就是C++模擬實(shí)現(xiàn)string的詳細(xì)過程的詳細(xì)內(nèi)容,更多關(guān)于C++模擬實(shí)現(xiàn)string的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論