關於 AnsiString 的問題
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ; //此時為引用方式 : str2.data = str1.data
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
我是在用B2006時發現如此(str1 = str2 = "hello ")
印象中B6不是這樣的,希望哪位好人用B6幫忙測試一下:
AnsiString str2 = str1 ; //該方式下是否重新構造一個新的字符串
AnsiString str2 = str1.c_str() ;//這樣是肯定重新構造一個新的字符串的
[解决办法]
帮大虾cb6环境测试了
ShowMessage结果
B6中也是
str1 = str2 = "hello "
[解决办法]
void __fastcall TForm1::Button2Click(TObject *Sender)
{
String str1 = "Hello ";
String str2 = str1.c_str() ;
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
}
这样确实 str1 大写了
[解决办法]
关注,最近想找个bcb编译段代码都找不到,帮不上忙.
个人认为应该构造一个新的.AnsiString类的代码还没看过,汗一下.如果这样引用好像不太合理.
[解决办法]
测试了,同上!
[解决办法]
再汗一下.
[解决办法]
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ; //此時為引用方式 : str2.data = str1.data
AnsiString str3 = str1.c_str();
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2+ "\n str3 : " + str3);
输出 hello hello Hello
难道str1 ,str2引用的是同一块栈内存?????????
以前真的没有注意到这个问题
看来以后不能随便 用 =操作符来复制字符串了
[解决办法]
偶也一直没发现这个问题,试了一下:
AnsiString str1= "Hello ";
AnsiString str2=str1;
str2[1]= 'h '; //改成这样就好了
//char *p=str2.c_str();
//p[0]= 'h ';
ShowMessage( " str1 : " + str1 + " str2 : " + str2);
结论是尽量不要直接给c_str()或data()赋值(又回到老调上去了)
[解决办法]
system.pas的汇编代码LStrAsg,就这样弄的。为什么这样?
[解决办法]
发现在AnsiString内部不仅保留了长度,还做了一个是否引用的标记,
在对AnsiString进行修改时,如果是引用则调用NewString!
char *=c_str.的方式,就用不上这个机制。也就出错!
[解决办法]
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ; //此時為引用方式 : str2.data = str1.data
str2 += "1234 ";
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
结果:
---------------------------
str1 :Hello
str2 : hello1234
---------------------------
[解决办法]
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ; //此時為引用方式 : str2.data = str1.data
str2.SetLength(3);
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
结果:
---------------------------
str1 :Hello
str2 : hel
---------------------------
[解决办法]
应该是c_str引起不安全
[解决办法]
MARK。。。
[解决办法]
const char *p = str2.c_str() ;
//c_str() 是 const char* 常量指针类型, 所以不行
//需要定义为 const char *p=str2.c_str();
//char 与String类型也不一样, 所以这样定义是不太安全.
//如果需要实现 指向str2指针, 可以用AnsiString *p = &str2;
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ; //此時為引用方式 : str2.data = str1.data
AnsiString *p = &str2;
*p = "h " ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
[解决办法]
有深度呆...呵呵
[解决办法]
看到操作符的定义
AnsiString& __fastcall operator =(const AnsiString& rhs);
是地址操作的,可能问题出现在这里吧.
[解决办法]
听说BCB有源代码的
看看AnsiString的源代码?
[解决办法]
关注
[解决办法]
AnsiString& __fastcall operator =(const AnsiString& rhs);
[解决办法]
应该是c_str()引起的问题
[解决办法]
c_str()不安全,我也碰到同样的问题。调用api时错。
[解决办法]
出差呢
看到高人的帖子
拜访一下
[解决办法]
小的不才,说上几句。
AnsiString str1 = "Hello ";
AnsiString str2 = str1 ;
char *p = str2.c_str() ;
*p = 'h ' ;
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2);
楼主对str1和str2出现相同的值觉得奇怪,其实一点也不奇怪,而是楼主对AnsiString的设计明显一知半解,直言了。:)
下面对各语句解释一下:
AnsiString str1 = "Hello "; // 这里是用构造函数,生成一个新的AnsiString.
AnsiString str2 = str1 ; // 这里是引用操作,str2和str1都指向同一块内存区域
// 如果这时ShowMessage(str2)和ShowMessage(str1)当然一样。相信大家不奇怪。
char *p = str2.c_str();// p获得了一个对str2数据域的一个指针,也就是str1数据域指针。
*p = 'h '; // 这里改变了str2指向的数据域的首字符。其实也是str1的,楼主错以为只是改变了str2, 而与str1无关。
ShowMessage( " str1 : " + str1 + "\n str2 : " + str2); //str1和str2还是指向同一个地方
说明:重点是str2=str1这句,楼主也是知道这是一个引用操作的,为什么却反而想让*p= 'h ';这句只改变str2,而不改变str1呢。实际上如果还有str3,str4,它们也都是同一个值。因为本质上它们都指向同一个地方。那么什么时候才不一样呢?其实AnsiString在设计时使用了write-copy技术,也就是说在你修改str2时,系统才先把str1原来的内容重新复制一分,让str2指向这个新生的内存区域,然后再进行操作,比如str2[1] = 'h '; //不同于*p = 'h ',
那么系统为什么这样设计呢,当然是一个效率的问题!如果str2 = str1这句真的是直接把str1的数据COPY到str2对象里的话,无论是时间还是空间都是很浪费的。特别是str1包含的数据量比较大的时候。只有当系统发现你修改str2的时候系统才会使用write-copy技术。*p=str2.c_str()只是获得了一个对str2(也是str1)的数据域的指针,此时直接修改*p= 'h ',系统是不会认为你要改变str2而不改变str1的,这只是一个对内存块首字字符的赋值而已,而str2[1]=‘h’就不一样了。
BCB的help其实也是给出一说明的:
char* __fastcall c_str() const; //注意这里的const表示这个函数自身不改变数据域的数据,但char *不是一个const char *,表示你可以对过char *直接修改数据域的数据,这也是为了提高效率,如果是const char*,你只能通过AnsiString自身的方法改变其内容了。
Description
c_str returns a pointer a null-terminated character array containing the same characters as the AnsiString. If the AnsiString is unassigned, c_str returns an empty string (摂).
Usually, the value returned by c_str points to the internal character array referenced by the data property. This pointer is valid until the string is next modified (for example when the SetLength method is called or the AnsiString goes out of scope). However, if the internal array is NULL, c_str returns a pointer to a string literal.
The c_str method is intended primarily for reading the value of the AnsiString. To modify the string抯 value, use the [] operator or AnsiString methods such as Insert and Delete.
各位大侠见笑了。:)
[解决办法]
仔细楼上发的这个描述
觉得应该是这样的
我一直觉得AnsiString 做的有点象JAVA的String类 看来是真的
那么同理
AnsiString sz = "abcde "
sz = "efgh "
对象sz肯定引用了 重新开辟的栈空间(java应该是在堆区)
这样设计 理论上是合理的
[解决办法]
楼上说的确实是有道理的,以后大家注意点就好。:)
[解决办法]
AnsiString str1 = "Hello! ";
AnsiString str2 = str1; // 此时根本没有新增空间,只是引用了str1 的地址,字串计数器加1
str1.c_str()[0] = 'h '; 修改了实际内存中数据, 此时 str2 的地址并未改变,因此,他也变成了 "hello! "
[解决办法]
学到了东西了