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++封装的类内部做了些什么。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值