【C++深度剖析教程15】经典问题解析之关于string的疑问
今天來看一下在面試筆試中經(jīng)常會出錯的地方。
我們先來看一個代碼:
看一下這個代碼,第一感覺是沒有什么問題的,指針p指向了S這個字符串,那么當(dāng)執(zhí)行 s.append(“abced”);這句話之后,字符串S會增加“abced”這借個字符,那么打印輸出的結(jié)果應(yīng)該為:12345和12345abced。但是我們運行程序發(fā)現(xiàn)(糾錯:使用gcc 4.4.7版本編譯器),兩條打印語句都是12345.這是為什么呢?下面我們看圖詳細分析一下:
一開始只是字符串S指向0xFF112233這個內(nèi)存空間,然后讓P指向這個空間,執(zhí)行這句話后:s.append(“abced”);S這個字符串變成了0x12345abced,同時這個字符串所對應(yīng)的地址空間卻變成了:0xFF445566,但是此時指針P依然指向之前的0xFF112233,里面的值是沒有變化的,為什么出現(xiàn)這種情況呢?
因為:string對象維護了一個指向數(shù)據(jù)的char*指針,這個指針在程序運行階段,有可能會發(fā)生突變。
所以那個P指針還是指向原來的0xFF112233這個地址,打印輸出的內(nèi)容就還是12345了。
糾錯:
- 針對上述的說明,有網(wǎng)友提出質(zhì)疑,在vs2013上運行結(jié)果就是12345和12345abced。我也做了實驗,在vs2017上運行結(jié)果也是12345和12345abced。而在我的Linux中,使用gcc
4.4.7版本編譯器,運行結(jié)果就是12345和12345。使用gcc 7.3.0 編譯器,就得到12345和12345abced 這個結(jié)果。很明顯,這與編譯器實現(xiàn)有關(guān),比較新版本的編譯器可以得到正常的運行結(jié)果。 - 很明顯,我一開始的分析,也是有一些錯誤的。string對象維護了一個指向數(shù)據(jù)的char* 指針,這個指針在程序的運行階段是有可能發(fā)生突變,也有可能不發(fā)生突變。比較新的編譯器編譯都沒有發(fā)生突變,說明比較新的編譯器解決了那個bug。
- 在我下面的評論中,我之前說可以從另一個角度理解為什么打印結(jié)果一樣,就是const,這種說法也是不對的,const修飾的變量,則該變量不能出現(xiàn)在賦值符號的左邊,不能被直接改變,但是可以被間接改變。
下面再看一個程序:
#include <iostream> #include <string>using namespace std;int main() {const char* p = "12345";string s = "";s.reserve(10); //分配內(nèi)存大小為10// 不要使用 C 語言中的方式操作 C++ 中的字符串for(int i=0; i<5; i++){s[i] = p[i];}cout << s << endl;return 0; }這個程序運行結(jié)果為:空!!!
為什么呢?難道對S的賦值沒有成功么?我們給出分析,用C語言描述C++中的字符串,會出現(xiàn)一些異常,看圖:
這里可以看出,m_cstr是指向字符串的內(nèi)容,m_length是string類的成員變量,它指向字符串的長度,經(jīng)過for循環(huán)后,我們操作的不是對象的整體,m_cstr所指向的字符串確實有了,但是m_length卻依然為0,所以最后打印出來的是空,我們應(yīng)該直接操作這個對象,才能讓m_length隨著賦值而改變。
我們把程序改成這樣:
#include <iostream> #include <string>using namespace std;int main() {const char* p = "12345";string s = "";s.reserve(10);s = p; //直接操作對象,不要像C語言那樣進行for循環(huán)賦值。// 不要使用 C 語言中的方式操作 C++ 中的字符串/*for(int i=0; i<5; i++){s[i] = p[i];}*/ cout << s << endl;return 0; }打印結(jié)果為:
這下就是我們期待的結(jié)果了。
總結(jié)一下:
-string類通過一個數(shù)據(jù)空間保存字符串?dāng)?shù)據(jù)
-string類通過一個成員變量保存當(dāng)前字符串的長度
-C++開發(fā)時,盡量避免C語言的一些慣用的編程思想
想一起探討以及獲得各種學(xué)習(xí)資源加我:
qq:1126137994
微信:liu1126137994
可以共同交流關(guān)于嵌入式,操作系統(tǒng),C++語言,C語言,數(shù)據(jù)結(jié)構(gòu)等技術(shù)問題。
總結(jié)
以上是生活随笔為你收集整理的【C++深度剖析教程15】经典问题解析之关于string的疑问的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 音乐播放器
- 下一篇: JVM直接内存