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

C++ String部分成員模擬實(shí)現(xiàn)流程詳解

 更新時(shí)間:2022年08月29日 10:12:37   作者:小小酥誒  
我們先不直接實(shí)現(xiàn)完整版的string,先實(shí)現(xiàn)簡(jiǎn)易版的string部分成員來基本了解下它的框架,以及以后來學(xué)習(xí)深淺拷貝的問題。這樣有循序漸進(jìn)的過程嘛

string類的成員設(shè)計(jì)

	class string
	{
	private:
		char* _str;
		int _size;
		int _capacity;
	};

說明:以下的五個(gè)成員函數(shù)的模擬實(shí)現(xiàn),均去除了_size_capacity成員變量,目的是為了更方便解釋重點(diǎn)。在五個(gè)成員函數(shù)模擬后,會(huì)對(duì)string類的設(shè)計(jì)進(jìn)行補(bǔ)全。

普通構(gòu)造函數(shù)的模擬

我們是否可以使用默認(rèn)構(gòu)造函數(shù)來初始化對(duì)象?在這種情況下是萬萬不能的!要記住默認(rèn)的構(gòu)造函數(shù)對(duì)自定義類型會(huì)去調(diào)用它自己的構(gòu)造函數(shù)進(jìn)行初始化,而對(duì)于內(nèi)置類型是不做處理的,此時(shí)我們的成員變量_str的類型是內(nèi)置類型,不會(huì)被初始化,所以一定要自己寫構(gòu)造函數(shù)。

//這種構(gòu)造函數(shù)是否可行?
string(const char* str)
{
	_str = str;
}

這種寫法做不到用字符串構(gòu)造一個(gè)對(duì)象。

原因:這樣會(huì)使得str_str指向的都是同一塊空間。str會(huì)影響到_str.

所以正確的做法是,給_str分配一塊屬于自己的空間,再把str的值拷貝給_str.

string(const char* str)
{
	_str = new char[strlen(str) + 1]; //要多給一個(gè)'\0'的空間
	strcpy(_str, str);
}

修一下小細(xì)節(jié):

1.實(shí)例化對(duì)象的時(shí)候是支持無參構(gòu)造的,所以可以給參數(shù)一個(gè)缺省值"",里面自己隱藏的有一個(gè)\0.如果沒有傳參數(shù),則使用缺省值。

string(const char* str = "")
{
	_str = new char[strlen(str) + 1]; //要多給一個(gè)'\0'的空間
	strcpy(_str, str);
}

拷貝構(gòu)造函數(shù)的模擬

看了普通構(gòu)造函數(shù)的模擬實(shí)現(xiàn)以后,最不應(yīng)該犯的錯(cuò)就是把一個(gè)string對(duì)象的數(shù)據(jù)直接給了另一個(gè)string對(duì)象

所以直接甩代碼

string(const string& s)
{
	_str = new char[strlen(s._str) + 1];
	strcpy(_str, s._str);
}

當(dāng)然,如果有前面所寫普通構(gòu)造函數(shù),還可以利用普通構(gòu)造函數(shù)來拷貝構(gòu)造一個(gè)對(duì)象。

//還可以借助普通構(gòu)造函數(shù)
string(const string& s)
	:_str(nullptr)
{
	string tmp(s._str);
	swap(_str, tmp._str);
}

賦值重載函數(shù)的模擬

這里重載賦值,是為了把一個(gè)已經(jīng)存在的string對(duì)象的數(shù)據(jù)給另一個(gè)已經(jīng)存在的string對(duì)象。

也就意味著,兩個(gè)對(duì)象均有自己的空間。不要把string對(duì)象的_str直接賦值,否則析構(gòu)的時(shí)候會(huì)析構(gòu)兩次,并且這兩個(gè)string對(duì)象由于_str使用的是同一塊空間,會(huì)相互之間影響。

string& operator=(const string& s)
{
	delete[] _str; //把原來的空間釋放掉
	_str = new char[strlen(s._str) + 1]; //給一塊新的空間
	strcpy(_str, s._str);;
}

上面這種方法是不行的。

1.不排除自己給自己賦值的情況,自己都給釋放了,拿什么來賦值?

2.使用delete先釋放,只要地址正確無論如何都會(huì)釋放成功,但是new一塊空間不一定會(huì)成功,如果一開始就給釋放了,而我去申請(qǐng)空間卻申請(qǐng)不到,那就是不僅沒有賦值成功,還把我自己原本有的給丟了。

//正確的寫法
string& operator=(const string& s)
{
	if (this != &s)
	{
		char* tmp = new char[strlen(s._str) + 1];
		strcpy(tmp, s._str);
		delete[] _str;
		_str = tmp;	
	}
	return *this; //如果自己給自己賦值,那就返回自己
}

還可以使用傳值的方法

string& operator=(string s)
{
	swap(_str, s._str);
	return *this;
}

String的析構(gòu)函數(shù)模擬

~string()
{
	if (_str)
	{
		delete[] _str;
		_str = nullptr;
	}
}

補(bǔ)全上述的成員函數(shù)

//因?yàn)閟td庫里原本有一個(gè)string,所以這里加上一個(gè)命名空間,防止命名污染
namespace YDY
{
	class string
	{
	public:
		string(const char* str = "")
			:_size(strlen(str))
			,_capacity(_size)
		{
			_str = new char[_capacity + 1]; //要多給一個(gè)'\0'的空間
			strcpy(_str, str);
		}
		string(const string& s)
			:_str(nullptr)
			,_size(s._size)
			,_capacity(s._capacity)
		{
			string tmp(s._str);
			swap(_str, tmp._str);
		}
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[strlen(s._str) + 1];
				strcpy(tmp, s._str);
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
			_size = _capacity = 0;
		}
	private:
		char* _str;
		int _size;
		int _capacity;
	};
	void test()
	{
		string s1;
		string s2(s1);
		string s3 = s1;
	}
}

迭代器的簡(jiǎn)單模擬

		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;
		}

其他成員函數(shù)的模擬

		const char* c_str()
		{
			return _str;
		}
		size_t size()
		{
			return _size;
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];
		}
		//reserve
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				//擴(kuò)容到n+1
				//tmp是內(nèi)置類型,
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;

				_capacity = n;
			}
		}
		//
		void push_back(char c)
		{
			//空間不夠,擴(kuò)容
			if (_size == _capacity)
			{
				//擴(kuò)容
				reserve(_size + 1);
			}
			_str[_size] = c;
			_size++;
			_str[_size] = '\0';
		}
		void append(const char* str)
		{
			int len = strlen(str);
			if (_size + len > _capacity)
			{
				//增容
				reserve(_size + len);
			}
			strcpy(_str + _size, str);
			_size += len;
		}
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+=(const char* str)
		{
			//復(fù)用追加函數(shù)append()
			append(str);
			return *this;
		}
		//任意位置的插入
		string& insert(size_t pos, char ch)
		{
			if (_size == _capacity)
			{
				reserve(_size + 1);
			}
			//開始插入
			int end = _size + 1;
			//找到pos的位置,并留出pos的位置以便插入
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos < _size);
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				//增容
				reserve(_size + len);
			}
			//找到pos的位置,并且留出要插入的位置
			size_t end = _size + len;
			while (end > pos)
			{
				_str[end] = _str[end - len];
				end--;
			}
			//開始插入
			strncpy(_str + pos, str, len);
			return *this;
		}
		//從pos的位置開始刪除len的長(zhǎng)度
		string& erase(size_t pos = 0, size_t len = std::string::npos)
		{
			assert(pos < _size);
			if (len == std::string::npos || pos + len > _size)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
			return *this;
		}

到此這篇關(guān)于C++ String部分成員模擬實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)C++ String成員模擬實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++ 類中const成員變量的賦值方法

    c++ 類中const成員變量的賦值方法

    下面小編就為大家?guī)硪黄猚++ 類中const成員變量的賦值方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • C++字符數(shù)組的輸入輸出和字符串結(jié)束標(biāo)志使用講解

    C++字符數(shù)組的輸入輸出和字符串結(jié)束標(biāo)志使用講解

    這篇文章主要介紹了C++字符數(shù)組的輸入輸出和符串結(jié)束標(biāo)志使用講解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C++嵌套類與局部類詳細(xì)解析

    C++嵌套類與局部類詳細(xì)解析

    從作用域的角度看,嵌套類被隱藏在外圍類之中,該類名只能在外圍類中使用。如果在外圍類之外的作用域使用該類名時(shí),需要加名字限定
    2013-09-09
  • C語言音樂播放器實(shí)例代碼

    C語言音樂播放器實(shí)例代碼

    文章給大家分享了用C語言音樂播放器的實(shí)例代碼,對(duì)此有需要的朋友參考學(xué)習(xí)下。
    2018-07-07
  • C++中類模板的應(yīng)用你了解多少

    C++中類模板的應(yīng)用你了解多少

    這篇文章主要為大家詳細(xì)介紹了C++中類模板的應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C++實(shí)現(xiàn)多項(xiàng)式相乘

    C++實(shí)現(xiàn)多項(xiàng)式相乘

    這篇文章主要介紹了C++實(shí)現(xiàn)多項(xiàng)式相乘方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C++ STL中一些常用算法總結(jié)

    C++ STL中一些常用算法總結(jié)

    都說STL是數(shù)據(jù)容器與算法的高度組合,在前面的文章中我們介紹了常見的幾種容器,vector、list、map、deque等,今天我們?cè)賮斫榻B下STL中常用的一些算法,需要的朋友可以參考下
    2024-02-02
  • C++簡(jiǎn)單實(shí)現(xiàn)Dijkstra算法

    C++簡(jiǎn)單實(shí)現(xiàn)Dijkstra算法

    這篇文章主要為大家詳細(xì)介紹了C++簡(jiǎn)單實(shí)現(xiàn)Dijkstra算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語言基礎(chǔ)指針詳解教程

    C語言基礎(chǔ)指針詳解教程

    此處對(duì)于指針做一些簡(jiǎn)要的介紹,作者實(shí)屬初學(xué),寫博客也是作者學(xué)習(xí)的一個(gè)過程,難免文章中有內(nèi)容理解不到位或者有不當(dāng)之處,還請(qǐng)朋友們不吝指正,希望大家給予支持
    2021-11-11
  • C++使用WideCharToMultiByte函數(shù)生成UTF-8編碼文件的方法

    C++使用WideCharToMultiByte函數(shù)生成UTF-8編碼文件的方法

    用來映射Unicode字符串的WideCharToMultiByte函數(shù)經(jīng)常被用來進(jìn)行UTF-8編碼的轉(zhuǎn)換,以下我們將看到C++使用WideCharToMultiByte函數(shù)生成UTF-8編碼文件的方法,首先先來對(duì)WideCharToMultiByte作一個(gè)詳細(xì)的了解:
    2016-06-06

最新評(píng)論