分析(未完且有错)

如果我们有一个子函数,返回值是string类型对象:

那么我们在主函数中常使用char类型指针去接收它的返回对象:

当我们用:

输出p指向的字符数组时,会输出“sssssssssssssssssss”吗?答案是否定的:

我曾一度认为因为可以做类似如下的定义:

且可以输出正确的结果:

则上边的用p接收teststr()返回的值就可以是正确的,然而事实并不是这样

我们反汇编跟踪一下,会发现:

调用之后局部变量中确实会多出来一个teststr()返回对象的拷贝:

观察此时teststr returned的地址:

 

teststr()的返回值teststr returned的地址保存在寄存器eax中:

当执行过c_str(),即将string对象转变成字符数组时,eax中的值也会改变:

我们知道,通常情况下eax中保存的是函数的返回值,那么我们来看看这里的eax保存的是什么呢?

原来是"sssssssssss"字符数组的首地址,而这个首地址就是通过c_str()函数得到的。这个首地址保存在eax中,之后会赋给指针p:

可以看到mov之后,p中存放的值就是eax中的值,即“sssssssssssssssss”的地址:

那么问题来了,既然这样,为什么“cout<<p<<endl”会输出乱码呢?

当我们执行过:

char转换这一步后,p保存的地址没有变,而p保存的地址指向的内容却改变了

经思考,原因是这样子的,teststr()返回的是一个string对象,而p是一个char类型的指针,p只能接收并保存teststr()返回的对象的地址“0x0083aab0”,而不能真正保存返回的string对象,那么直到运行完

甚至main()函数彻底结束之前,p都很好的保存着“0x0080aab0”这个值,它很好的完成了自己的任务,但他没有足够的能力保存“sssssssssssssssssss”。虽然“teststr returned”是一个string对象,但是,它却仅仅是一个临时的对象,它在运行完它所在的那一行代码之后就被释放了,也就是说“teststr returned”的生命周期就只有这一句。对“teststr returned”进行完c_str()操作和(char *)操作之后,“teststr returned”遍释放掉了。

除非,你用一个string类型对象保存teststr()的返回对象,例如:

因为stmp是建立了一个新的string对象接收“teststr returned”:

这时,我们利用监视窗口观察一下stmp和“teststr returned”的地址:

发现是相同的:

那么问题又来了,为什么上面提到的经过c_str()转换之后,eax保存的指针0x0080aab0位置所保存的内容可以直接看到“sssssssssssssssss”,而为什么此时的"teststr returned"和stmp指向的地址相同,而看到的就不是字符数组,而是0043ab10?

原因很简单,这里的"teststr returned"和stmp指向的是“对象”即string类型对象,它不单单是简单的字符数组。string是一个类,它不是只存储数据“ssssssssssssss”,还包括了一些成员函数,所以不能等同于字符数组。

posted @ 2015-10-23 10:04  _No.47  阅读(187)  评论(0编辑  收藏  举报