关于C++ string类的写时复制

问题代码:

 //将strGrammar的第(pos+1)个字符向后移动一位 
void BackMovePoint(string& strGrammar, int pos)
{

     char* grammar  = const_cast<char*>(strGrammar.c_str());//  正确的写法: string grammar = (char*)(strGrammar.c_str());

    char temp = grammar[pos];
    grammar[pos] = grammar[pos + 1];
    grammar[pos + 1] = temp;
    strGrammar = "";
    int nLength = strlen(grammar); // grammar.length(); 
    for (int i = 0; i < nLength; i++)
        strGrammar += grammar[i];
}

 

在另一个函数中调用此函数:

for (int m = 0; m < vecSameEntrance.size(); m++)  //vecSameEntranc类型:vector<string>
   {
     log <<"m: "<<m<<' ' << vecSameEntrance[m]<< ' ' << __LINE__ << endl;

       string tempStr=vecSameEntrance[m];

       int pointIndex = tempStr.find('.',0);
   

       if (pointIndex < tempStr.length() - 1)
       {
           BackMovePoint(tempStr, pointIndex);

           pointIndex = tempStr.find('.', 0);
           if (pointIndex == tempStr.length() - 1)
               bNodeEnd = true;
   
           ProduceCLOSUE(newvecGrammar, tempStr, vecGrammar);
      log <<"after: "<<"m: "<<m<<' ' << vecSameEntrance[m] << ' ' << __LINE__ <<endl;

     }

}

 

日志输出:

m: 0 S->.E 493
after: m: 0 S->E. 508
m: 1 E->.E+E 493
after: m: 1 E->E.+E 508
m: 2 E->.E*E 493
after: m: 2 E->E.*E 508

 

vecSameEntrance中的值本不应改变的,但在调用BackMovePoint之后全都改变了!由于程序其他地方还使用到此变量,由于变量的改变导致程序崩溃。调了一个下午才找到原因:string类的写时复制!tempStr与vecSameEntranc中的string值其实是共享同一块内存,指向的是同一个内存地址,在BackMovePoint将tempStr强制转换const_cast<char*>成char*,并进行改写,导致vecSameEntrance对应的string的值也被修改。

 

关于string类的写时复制:

string类内存:string类中必有一个私有成员,其是一个char*,用户记录从堆上分配内存的地址,其在构造时分配内存,在析构时释放内存。因为是从堆上分配内存,所以string类在维护这块内存上是格外小心的,string类在返回这块内存地址时,只返回const char*,也就是只读的,如果你要写,你只能通过string提供的方法进行数据的改写。

 

详见:标准C++类std::string的内存共享和Copy-On-Write技术,作者:陈皓http://blog.163.com/digoal@126/blog/static/163877040201011318659953/

作者分析的相当精彩,C++是一把双刃剑,只有了解了原理,你才能更好的使用C++。否则,必将引火烧身。如果你在设计和使用类库时有一种“玩C++就像玩火,必须千万小心”的感觉。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值