问题来源:

  在写二叉树序列化与反序列化时发现序列化函数为char* Serialize1(TreeNode *root)  其函数返回类型为char*,但是我在实现的过程中为了更方便的操作添加字符串使用的是C++中string类型的变量,这就导致我最后得到的结果res是string类型,若是要返回需要转化为char *类型。而等我将string类型转为char*后返回在主函数中就成了乱码。

先直接说最后的解决办法:

  第一种:定义一个char数组,数组长度为stringlength+1,将string的内容依次赋值给char数组,最后加上'\0' ,然后返回char数组名就行了。

  第二种:将string定义为类的成员变量

  就贴第一种方法的代码

char *result = new char[res.length() + ];  //定义需要返回的result对象
for (int i = ; i < res.length(); ++i)
{
result[i] = res[i];    //将string类型的res内容都放到result内
}
result[res.length()] = '\0';  //加上结束符\0

再说说我尝试的方法

尝试1:

  一开始我是直接定义char *result=&res[0];想要通过这个语句直接返回这个string类型变量的首地址,但是失败了,在主函数中的结果变量是乱码 "葺葺葺葺葺葺葺葺葺葺"

尝试2:

  于是我开始思考可能的原因  

  1.考虑到局部变量可能随着函数释放,因此导致我返回的指针指向的内容随着函数一起释放导致了乱码,但一想到平时写的函数都是正常返回的,所以这个我很快否决了,但最后发现这个思路是对的。至于平常写的函数都是正常返回则是因为没有涉及到类型转换。  

  2.通过VS的调试发现我使用的char *result=&res[0]语句返回的是res的首个元素地址,并不是res的首地址,因为string作为std封装的数据结构除了char*这种从C吸收过来的结构还有内存分配allocate这些东西所以导致其内存地址并不像char数组那样是首个元素地址

  所以我想干脆把整个string类型的res都赋值给char *类型的result

  所以我尝试了char *result=(char*)res.data();语句,将res(res是string类型的结果)赋给result,转换是成功的,但返回值依旧失效(且这种转换需要自己加上\0结束符)

  然后尝试char *result=(char*)res.c_str(); 结果也是成功的,但返回值依旧失效。

  最后尝试,用new新建一个char数组,将res的内容全部拷贝到char数组内,然后将数组名返回,终于成功。

问题根源

  通过VS调试我最终发现了问题根源所在:res所占内存随着函数结束而被释放

  这是函数未执行完的调试界面

  这是执行完调试界面

  很明显:res没有了,在函数执行完毕后res内存也跟着被释放了而char数组result却仍然存在。他们的不同点在哪:result是返回值 

  我们知道函数的函数栈知识点,栈内存放着函数入口地址,局部变量,返回地址等,我猜测result作为要被返回的对象其内存空间应该是不随着函数一起被释放的,也就是主函数内的返回值应该还是用那块内存,经过测试这个结论是对的。主函数中的变量的确是使用返回值那块内存。

  到这里就发现了,虽然执行char* result=(char*)res.c_str()语句能让result内是完整的结果内容(也就是转换完成),但result会随着string类型的res的释放而导致char*类型的result所指向的内存空间内容全部清空。最后虽然返回了result所指的空间但里面的内容早就被清空了。就好比把内存比作一块地,res先在其上面盖了一座房子,而使用上面转换语句后result也是房子的主人,这下房子有了两个主人,他们都能对房子进行操作。正因为他们都能进行操作,当他们所属函数结束也就是res大限到来之时,res将自己建立的房子销毁了。那么result也就没有房子可住了。也就是他们公用的那片内存被初始化,这时主函数虽然收到了返回地址但那片地址已经没有内容了。也就导致乱码了。

  到这里,问题的根源就知道了,那么解决方法也就很明显了:1.内存分离,将res和result的所属内存地址分开。2.或者想办法让res所在内存不随着函数结束而释放.

  具体实现:

  第1种.上面那段new新建char*变量的代码。为result重新开辟一段空间。

  第2种.i:若在类里:将res设为类的成员变量或者static成员变量(最好不要,能成功但会有新问题出现),他们都不会随着成员函数的结束而释放。区别就是普通成员变量会随着对象的释放而释放,static不会,它是存放在静态存储区

      ii:若是像C这类面向过程代码就是将res设为全局变量即可

C++中string转换为char*类型返回后乱码问题的更多相关文章

  1. c++ string类型转换为char *类型

    string 是c++标准库里面其中一个,封装了对字符串的操作 把string转换为char* 有3中方法: 1.data 如: string str="abc"; char *p ...

  2. C++中string、char *、char[]的转换

    头段时间有人问过我这个问题,可是我一点头绪都没有,直接说不会.现在从网上找了点资料,看了看,知道点东西了. 一.string转char*. 主要有三种方法可以将str转换为char*类型,分别是:da ...

  3. C++ 将 std::string 转换为 char*

    参考: std::string to char* C++ 将 std::string 转换为 char* 目前没有直接进行转换的方法.必须通过string对象的c_str()方法,获取C-style的 ...

  4. C++中string和char字符串的异同与使用方法

    C++中string和char声明字符串的异同和使用 string类 必须在头文件中包含<string> 隐藏了字符串的数组性质,可以像处理普通变量那样处理字符串 string类位于名称空 ...

  5. 关于==和equals()方法&Java中string与char如何转换&String,StringBuffer

    1.对于基本数据类型,可以直接使用==和!=进行内容比较 如:int x=30;        int y=30;         x==y;  //true 基本数据类型 简单类型(基本类型) bo ...

  6. JS中String类型转换Date类型 并 计算时间差

    JS中String类型转换Date类型 1.比较常用的方法,但繁琐,参考如下:主要使用Date的构造方法:Date(int year , int month , int day)<script& ...

  7. C++11中string与数值类型的转换

    C++中string与数值类型的相互转换记录 string转int.double.long string s = "123.456"; // string -> int co ...

  8. Java中String转换Double类型 Java小数点后留两位

    Java中String转换Double类型 double num1 = 0.0; String qq = "19.987"; num1 = Double.valueOf(qq.to ...

  9. 如何把string转换char*类型

    需要调用string头文件  ( #include<string> ) 用string里的函数c_str()可以把string转换为char* 例如 char * c_str2=str1. ...

随机推荐

  1. 团体天梯赛L1-041.寻找250

    对方不想和你说话,并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字. 输入格式: 输入在一行中给出不知道多少个绝对值不超过1000的整数,其中保证至少存在一个“250”. ...

  2. @Transactional 事务的底层原理

    最近同事发现一个业务状态部分更新的bug,这个bug会导致两张表的数据一致性问题.花了些时间去查问题的原因,现在总结下里面遇到的知识点原理. 问题一:事务没生效 我们先看一段实例代码,来说明下问题: ...

  3. 聊一聊高并发高可用那些事 - Kafka篇

    目录 为什么需要消息队列 1.异步 :一个下单流程,你需要扣积分,扣优惠卷,发短信等,有些耗时又不需要立即处理的事,可以丢到队列里异步处理. 2.削峰 :按平常的流量,服务器刚好可以正常负载.偶尔推出 ...

  4. ubuntu18启动zabbix-agent失败/故障记录

    故障现象 ubuntu 16 升级18 之后 安装了zabbix agent 今天突然agent掉了 上去的时候发现 报错: 后来打算-c 启动然后发现 /usr/sbin/zabbix_agentd ...

  5. CoordinatorLayout简介

    CoordinatorLayout简介 CoordinatorLayout的作用 协调子view的布局,降低子view之间的耦合度 CoordinatorLayout的使用 核心:Behavior,用 ...

  6. C语言视频教程下载(百万年薪程序员录制,免费公开)

    <C/C++语言高性能服务开发基础>您可以自由下载.传播.发布或其它商业用途. 视频文件共13.6G,提供了QQ群文件和百度网盘两种方法,建议采用QQ群文件下载,速度较快. 一.下载方法 ...

  7. PuTTY通过SSH连接上Ubuntu20.04

    在PuTTY中连接到Ubuntu20.04大致需要几个步骤(不一定对应文本中的序号):1) 安装opensh-server (Ubuntu安装好之后 ,一般openssh-client自动已经安装好) ...

  8. 《Redis开发与运维》

    第1章 初识Redis 1. Redis介绍: Redis是一种基于键值对(key-value)的NoSQL数据库. 与很多键值对数据库不同的是,Redis中的值可以是由string(字符串).has ...

  9. Rigidbody(刚体)方法的初步学习(一)

    概要:这次将简单的了解Rigidbody中的各种方法属性,以官方的API为顺序研究. 蛮牛API翻译:Rigidbody组件控制物体的位置—它使物体在重力影响下下落,并可计算物体将怎样响应碰撞.当操作 ...

  10. Git配置仓库的用户名邮箱

    Git配置单个仓库的用户名邮箱 $ git config user.name "gitlab's Name" $ git config user.email "gitla ...