1、C++的std::string浅拷贝
这是帮朋友调适出来的一个错误,隐藏得很深,有些诡异。
全局指针 char* filename; 某函数中出现: function A() { std::string file = ;// 此处从其他地方获得文件名 filename = file.c_str(); // 将文件名复制后,然后到其他地方使用 // 这里错了!file是一个局部对象,当程序段离开这里后,file 就销毁了 // filename 指向 就指向了一片垃圾数据 } function B() { // 使用 filename } 如果两段代码在一个线程内,那么程序B处肯定会出现问题,因为filename指向的对象是垃圾数据。但如果,两段程序出现在两个不同的线程中,那么,表现出来的症状就不是这样了。
线程1: function A() { std::string file = ;// 此处从其他地方获得文件名 filename = file.c_str(); // 将文件名复制后,然后到其他地方使用 wxMessageBox("...message...");// 弹出一个对话框,阻塞这个线程 } 线程2: function B() { // 使用 filename } 倘若程序段B在关闭对话框之前取出 filename ,那么程序会执行正确;倘若程序段B在关闭对话框之后在取出filename,那么程序就会出现错误。也就是说,在加入了界面与线程以后,问题被隐藏的更深入了。因为它的表现具有一定的随机性,与你关闭对话框的动作相关。filename = file.c_str();是浅拷贝。数据区域并没有被拷贝。倘若将全局变量filename的类型设置为string,然后用filename = file做赋值操作,那么就不会出现这个问题了。因为这是一个深拷贝。
2.c++的std::string与Java的String 以前用Java String的时候,觉得这个类真的很好,屏蔽了太多的底层操作,用起来相当的方便,用c++的string觉得没这么方便了。简单的比较一下一些实现函数,发现c++串的功能并没有这么弱,只是平时用的太少了!
<o:p> </o:p> | C++ std::string<o:p></o:p> | Java String<o:p></o:p> |
创建字符串<o:p></o:p> | string s(“hehe”);<o:p></o:p> string s=”hello”;<o:p></o:p> | 类似<o:p></o:p> |
访问单个字符<o:p></o:p> | s[0] 不会进行范围检查<o:p></o:p> s.at(0) 会进行范围检查<o:p></o:p> | charAt(i)<o:p></o:p> <o:p> </o:p> |
字符串比较<o:p></o:p> | S1.compare(s2)<o:p></o:p> 等于返回0,大于返回正数<o:p></o:p> | compareTo返回整型,>0表示大于,=表示等于<o:p></o:p> equals返回bool,true表示相等<o:p></o:p> == 比较两者引用是否相同,不比较内容<o:p></o:p> |
连接字符串<o:p></o:p> | S = s1+s2+s3;<o:p></o:p> S = s1.append(s2); 只能连接string与char*类型,int,float等不行 | append()<o:p></o:p> "+"号功能更强大,不仅能连接串,而且能连接 int,float等类型<o:p></o:p> |
字符串查找<o:p></o:p> | s.find(ss) <o:p></o:p> | indexOf<o:p></o:p> |
字符串替换<o:p></o:p> | s.replace(pos,search.size(),search)<o:p></o:p> | replace<o:p></o:p> |
提取字串<o:p></o:p> | s.substr(startpos,len)<o:p></o:p> | substring<o:p></o:p> |
删除与插入字串<o:p></o:p> | insert<o:p></o:p> erase<o:p></o:p> | delete<o:p></o:p> insert<o:p></o:p> |
其他<o:p></o:p> | string定义为typedef basic_string <char> string<o:p></o:p> | 当字符串经常发生变化时,需要用StringBuffer替换String; |