问题来源:

  在写二叉树序列化与反序列化时发现序列化函数为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. java实现第四届蓝桥杯三部排序

    三部排序 题目描述 一般的排序有许多经典算法,如快速排序.希尔排序等. 但实际应用时,经常会或多或少有一些特殊的要求.我们没必要套用那些经典算法,可以根据实际情况建立更好的解法. 比如,对一个整型数组 ...

  2. Java基础(九)

    一.总述 多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务.通常,每一个任务称为一个线程,它是线程控制的简称.可以同时运行一个以上线程的程序称为多线程程序. 多进程与多线程的区别: ...

  3. ios支付签名认证

    一.解析json中参数的含义 private Long id; @ApiModelProperty(value = "创建时间") private Date gmtCreate; ...

  4. v-else-if(v-show)

    <div id="app"> <div v-if="type === 'A'"> A </div> <div v-el ...

  5. 「雅礼集训 2017 Day4」洗衣服

    题目   点这里看题目. 分析   首先考虑只有洗衣机的情况.我们可以想到,当前洗衣任务结束越早的洗衣机应该被先用,因此可以用堆来动态维护.   再考虑有烘干机的情况.很显然,越晚洗完的衣服应该越早烘 ...

  6. HotCorner-让Windows 10拥有macOS的触发角特性!

    目录 简介 软件功能 下载 安装 卸载 使用 License 作者 FAQ 简介 macOS上有一个很方便的功能:"触发角".通过这个功能可以设置当鼠标移动到屏幕的四个角时的触发事 ...

  7. macos的两个快捷键和一个小tip

    学校的linux协会介绍了一个免费的light轻量级加速器,昨天晚上十点左右的时候着手研究,发现其实就是一个代理服务器.在配置这个代理服务器的时候碰到了一些困难并最终都解决了.下面记录一下配置过程学到 ...

  8. redis缓存使用SpringDataRedis

    1. SpringDataRedis简介 1.1项目常见问题思考 我们目前的系统已经实现了广告后台管理和广告前台展示,但是对于首页每天有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪.那如何解决 ...

  9. 使用vuex中的store存储数据

    Vuex是一个专门为Vue.js应用程序开发的状态管理模式,这个状态自管理应用包括三个模式 state 驱动应用的数据源 view 以声明方式将state映射到视图 actions 响应在view上的 ...

  10. rust 编码模式

    ➜ hello_cargo git:(master) ✗ rustc --print code-models Available code models: small kernel medium la ...