赞
踩
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++封装的类内部做了些什么。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。