深入剖析C++中的string类
一,C語言的字符串
在C語言里,對字符串的處理一項都是一件比較痛苦的事情,因為通常在實現(xiàn)字符串的操作的時候都會用到最不容易駕馭的類型——指針。
比如下面這個例子:
//example 1:
char str[12] = "Hello";
char *p = str;
*p = ''h'';? //改變第一個字母
?
//example 2:
char *ptr = "Hello";
*ptr = ''h'';? //錯誤
?
第一個字符串時用數(shù)組開辟的,它是可以改變的變量。而第二個字符串則是一個常量,也就是字面值。ptr只是指向它的指針而已,而不能改變指向的內(nèi)容。
看兩者的匯編即可明了:
char p[] = "Hello";
004114B8? mov???????? eax,dword ptr [string "Hello" (4166FCh)]
004114BD? mov???????? dword ptr [ebp-10h],eax
004114C0? mov???????? cx,word ptr ds:[416700h]
004114C7? mov???????? word ptr [ebp-0Ch],cx
char *ptr = "Hello";
004114CB? mov???????? dword ptr [ebp-1Ch],offset string "Hello" (4166FCh)
可見用數(shù)組和用指針是完全不相同的。
要想通過指針來改變常量是錯誤,正確的寫法應(yīng)該是用const指針。
const char *ptr = "Hello";
?
?
二,初識string類
正是因為C風(fēng)格字符串(以空字符結(jié)尾的字符數(shù)組)太過復(fù)雜難于掌握,不適合大程序的開發(fā),所以C++標(biāo)準(zhǔn)庫定義了一種string類,定義在頭文件<string>。注意<string.h>和<cstring>都是錯誤的,這兩個頭文件主要定義C風(fēng)格字符串操作的一些方法,譬如strlen(), strcpy()等。第一個是C的頭文件格式,而第二個是C++風(fēng)格的頭文件,但是和<string.h>是一樣的,它的目的是為了和C兼容。
看下面例子:
//example 3:
string str("world");?? //可以用C風(fēng)格字符串初始化
string words = "Hello";
string greet = words;
string? join = greet + words;? //可以像基本類型一樣操作
?
但是如果試圖把string類型的對象直接賦給C風(fēng)格的字符串的話,編譯器會報錯的。
string var = "Olympic";
char *ptr = var;? //error!
?
但是實際應(yīng)用中這個問題也難以避免,很多時候我們還是需要將string類型的轉(zhuǎn)化為char*來實現(xiàn)自定義的操作,C++標(biāo)準(zhǔn)庫也為了和之前用C寫的程序兼容,于是可以用string的c_str()函數(shù)。
string var = "Olympic";
char *ptr = var.c_str(); //還不能被編譯
?
或者通過const_cast去掉其const屬性亦可
char *ptr=const_cast<char *>(var.c_str()); //correct!
這樣就可以通過ptr修改其指向的地址空間內(nèi)容
?
但是c_str()為了防止意外地修改string對象,返回的是const指針,所以上面這段代碼是不能被編譯的。正確的應(yīng)該是用const指針。
string var = "Olympic";
const char *p =?var.c_str(); //Correct!
?
這個c_str()方法在C++IO流操作上也被廣泛應(yīng)用。
在打開文件時,如果要指定文件名,可以用C風(fēng)格的字符串。如果用到string類型的字符串作為文件名時,就必須調(diào)用c_str()方法將其轉(zhuǎn)換為一個C風(fēng)格字符串。
//example 4:
string?? filename;? //定義文件名稱
cin >> filename;
ifstream.open(filename.c_str());? //要使用C風(fēng)格字符串
?
三, 深入了解string類
對string有一定了解以后,我們可以來了解C++標(biāo)準(zhǔn)庫定義的一系列豐富的字符串操作,當(dāng)然都是基于string類型。從某一種程度上來說,string就是一種字符容器。
標(biāo)準(zhǔn)庫為string定義了很多方法,包括構(gòu)造、插入(insert)、替換(assign和replace)、比較(compare)、查找(find)、刪除(erase)、連接(append)以及對子串的操作(substr)。而每一種操作都有很多種重載。
比如插入,除了包括標(biāo)準(zhǔn)容器的插入方式以外,string類本身還有一些特有的插入方法。
//example 5:
//與標(biāo)準(zhǔn)容器相同的插入操作:
str.insert(iter, value) //在迭代器iter之前插入value, 返回新元素的迭代器
str.insert(iter, n, value); //在迭代器iter之前插入n個value,返回void
str.insert(iter, begin, end); //在迭代器iter之前插入迭代器begin和end標(biāo)記范圍內(nèi)的元素,返回void
//string類特有的插入方法:
str.insert(pos, n, ch); //在下標(biāo)為pos的字符之前插入n個字符ch
str.insert(pos, str2); //在下標(biāo)為pos的字符之前插入string類型的對象str2的副本
str.insert(pos1, str2, pos2, len); //在下標(biāo)為pos1的z字符之前插入string類型str2中從下表為pos2開始的len個字符
str.insert(pos, cp); //在下標(biāo)為pos的字符前插入字符指針cp指向的C風(fēng)格字符串的副本
?
總之string是一種非常靈活的字符串類型,標(biāo)準(zhǔn)庫讓我們可以忽略內(nèi)存管理和具體實現(xiàn)方式,我們只需要關(guān)注其接口就好。并且初學(xué)者在使用字符串的時候也應(yīng)盡量使用這種類型,而不是C風(fēng)格的字符串。
當(dāng)然,無C語言學(xué)習(xí)經(jīng)歷的人可以例外。
總結(jié)
以上是生活随笔為你收集整理的深入剖析C++中的string类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运营商与厂商发力 智能机进入700元以下
- 下一篇: c/c++经典面试试题及标准答案