C++ 和C 语言混合代码导致的问题
C語言中操作字符串用C運行時函數:strtok, strcmp, strcpy等等,直接操作內存。在c++引入的字符串操作類std:string ,string類中必有一個私有成員,其是一個char*,用戶記錄從堆上分配內存的地址,其在構造時分配內存,在析構時釋放內存。因為是從堆上分配內存,所以string類在維護這塊內存上是格外小心的,string類在返回這塊內存地址時,只返回const char*,也就是只讀的,如果你要寫,你只能通過string提供的方法進行數據的改寫。
看如下代碼:
? 1 #include <string>
? 2 #include <cstring>
? 3 #include <iostream>
? 4
? 5 using namespace std;
? 6
? 7 int main(int argc, char*argv[])
? 8 {
? 9???? string g_str = "Wj Cy Beijing";
?10???? string?tmp = g_str;
?11
?12???? char *p_str = (char *)tmp.c_str();
?13???? char *saveptr = NULL;
?14???? int id = 0;
?15???? bool bCheck = true;
?16
?17???? cout << "g_str: " <<g_str << endl;
?18???? cout << "tmp:?? " << tmp << endl;
?19???? cout << "****************"<< endl;
?20
?21???? char *p = strtok_r(p_str, " ",&saveptr);
?22???? cout << "g_str: " <<g_str << endl;
?23???? cout << "tmp:?? " << tmp << endl;
?24???? cout << "****************"<< endl;
?25
?26???? strtok_r(NULL, " ",&saveptr);
?27???? cout << "g_str: " <<g_str << endl;
?28???? cout << "tmp:?? " << tmp << endl;
?29
?30???? return 1;
?31 }
這段代碼中是string和strtok_r混合代碼,我們期望的運行結果是:
g_str: Wj Cy Beijing
tmp:?? Wj Cy Beijing
****************
g_str: Wj Cy Beijing
tmp:?? WjCy Beijing
****************
g_str: Wj Cy Beijing
tmp:?? WjCyBeijing
即:g_str的結果保持不變,始終是”Wj Cy Beijing”
?
但實際運行結果卻是:
g_str: Wj Cy Beijing
tmp:?? Wj Cy Beijing
****************
g_str: WjCy Beijing
tmp:?? WjCy Beijing
****************
g_str: WjCyBeijing
tmp:?? WjCyBeijing
結果中g_str的結果發生了變化,且同tmp的值保持一樣,就像是tmp和g_str string 中的char *指的是同一個地址。用gdb 進行調試,發現:
(gdb) p g_str.c_str()
$1 = 0x603028 "Wj Cy Beijing"
(gdb) p tmp.c_str()
$2 =?0x603028?"Wj Cy Beijing"
兩者確實指向同一個地址0x603028。
?
查詢資料發現,string類有copy-on-write特性,即:用時才分配內存,看如下代碼:
main()
{
?????? string str1 ="hello world";
?????? string str2 = str1;
????
?????? printf ("Sharingthe memory:/n");
? ?????printf ("/tstr1's address:%x/n", str1.c_str() );
?????? printf ("/tstr2'saddress: %x/n", str2.c_str() );
?????
?????? str1[1]='q';
?????? str2[1]='w';
?
?????? printf ("AfterCopy-On-Write:/n");
?????? printf ("/tstr1'saddress: %x/n", str1.c_str() );
?????? printf ("/tstr2'saddress: %x/n", str2.c_str() );
?
?????? return 0;
}
運行結果如下:
Sharing the memory:
??????? str1's address:343be9
??????? str2's address:343be9
After Copy-On-Write:
??????? str1's address:3407a9
??????? str2's address:343be9
可見在str2第一次被賦值時,并沒有為其char*分配內存,而是和str1共享內存(0x343be9), 直到給其賦值時,才分配內存0x343be9.
?
現在回過頭來看一下我們開始時所寫的代碼片段:
? 9???? string g_str = "Wj Cy Beijing";
?10???? string?tmp = g_str;???? ??//此時tmp 和g_str 存放字符串的內存char *為同一塊
?11
?12???? char *p_str = (char *)tmp.c_str();? //p_str其實指向的就是g_str存放字符串的內存塊
?13???? char *saveptr = NULL;
?14???? int id = 0;
?15???? bool bCheck = true;
?
原因找到了,這也就不能理解string接口函數c_str()返回類型是const char* 了,返回const就是不想讓人修改string中類型的值。想修改的話,最好通過string提供的接口函數進行修改。當然,如果你非要通過c函數修改的話,可以這樣來聲明tmp:
string g_str = "Wj Cy Beijing";
string tmp(“”);
tmp.append(g_str);
?
最好不要寫c++和c混合的代碼,因為你不可能都知道c++封裝的類內部做了些什么。
?
?
總結
以上是生活随笔為你收集整理的C++ 和C 语言混合代码导致的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鼋头渚如何预约
- 下一篇: 和天下香烟一条多少钱?