說說string類

1. 爲什麼會有string類

  1. 處理char型數組,封裝標準C中一些字符串處理函數。

  2. 容器


2. 規格:有106個成員接口函數。

有如此之多的原因:

  1. 提高效率。(設計比較冗餘,爲了追求效率,省去了調用構造/析構函數及分配/釋放內存的時間)

  2. 用於實現常用操作


3.實現:C++標準沒有過多幹預,不同廠商有不同實現。


4.缺陷

  1. 不支持多進/線程;

  2. 模板技術水平沒跟上;

  3. 接口函數設計比較冗餘,同一個功能上實現了多次,而有一些功能卻沒有實現,且陷阱多;

  4. 不支持虛函數,阻止了多態性;

  5. 加劇了內存碎片問題。希望String類擁有自己的棧上內存來存放一些短字符串,而不需要總是去堆上分配內存。

  6. 採用的Copy-On-WriteCOW)技術,因爲內存的共享,導致了程序在“多線程”環境中及容易發生錯誤,如果分別在兩個線程中的string實例共享着同一塊內存,很有可能發生潛在的內存問題。

  7. 標準的string類不支持policy-base技術的錯誤處理。string遇到錯誤時,只是簡單地拋出異常。不可能要且要求所有的程序都要在使用string操作的時候try catch。解決建議:string類封裝自己的error-handling函數,並且可以讓用戶來定義使用哪一種錯誤處理機制。


5.String類的簡單實現

#include<iostream>
using namespace std;
class String
{
public:
	String();
	String(const char* str);
	~String();
	String(const String& s);
	String &operator=(const String & s);
private:
	char* _str;
};
String::String()
:_str(new char[1])
{
	//cout << "無參構造函數" << endl;
	_str = '\0';
}
String::String(const char* str = "")
    : _str(new char [strlen(str)+1])
{
	//cout << "帶參構造函數" << endl;
	strcpy(_str,str);
}
String::~String()
{
	//cout << "析構函數" << endl;
	delete[] _str;
}
String::String(const String& s)
    :_str(new char[strlen(s._str)+1])
{
	//cout << "拷貝" << endl;
	strcpy(_str,s._str);
}
//String& String::operator=(const String & s)
//{
//	cout << "一般賦值運算符重載" << endl;
//	//檢查自賦值
//	if (this == &s)
//		return *this;
//	//釋放原有的內存資源
//	delete[] _str;
//	//分配新的內存資源,並複製內容
//	_str = new char[strlen(s._str) + 1];
//	strcpy(_str, s._str);
//	//返回本對象的引用
//	return *this;
//}

//賦值的現代寫法
String& String::operator=(const String & s)
{
	//cout << "現代賦值運算符重載" << endl;
	if (this == &s)
		return *this;
	//創建臨時變量,用於交換
	String strtmp(s);
	char* ptmp = strtmp._str;
	strtmp._str = _str;
	_str = ptmp;
	//返回本對象的引用
	return *this;
}
int main()
{
	String s1("hello");

	String s2(s1);

	String s3 = s1;

	s1 = s2;

	system("pause");
	return 0;
}

輸出結果:

(1)一般賦值運算符重載函數

wKioL1dmVSyzI-srAAAMXXdUw10541.png

(2)現代賦值運算符重載函數

wKioL1dmVLLjh0zLAAAkHyoe0E8375.png

實現表明:

  1. 在現代賦值運算符重載函數中,創建了一個臨時String對象(運用了拷貝構造函數),因爲此臨時String對象的作用域爲整個現代賦值運算符重載函數,出了這個函數就調用析構函數釋放內存資源,所以,現代賦值運算符重載函數比一般賦值運算符重載函數多兩個輸出。

  2. 第三行:String s3 = s1;我們明明是想用賦值運算符重載,實際調用的卻是拷貝構造函數。這是因爲編譯器優化的緣故,把本需調用構造函數構造s3再調用賦值運算符重載函數把s1拷貝給s3,編譯器直接優化爲利用拷貝構造函數構造s3。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章