我们知道,string类为我们提供了很多的便利,我们用string类能方便的做字符串的各种操作,避免了我们直接操作char指针而产生的一些繁琐的操作,和内存泄露的可能性,可是string类也是有陷阱的。下面我们看这样一个例子,你能看出问题所在吗?

string getString()
{
return "just a test";
}
void test()
{
const char *pc = getString().c_str();
cout<<pc<<endl;
}

如果看不出来可以实际运行一下,会发现输不出结果来,这是为什么呢?

当我们写getString函数时,如果其返回类型是const char*我们可能会分外小心,因为我们知道"just a test"生命会在函数返回后结束,我们可能会new一段空间来放这个字符串,然后返回指针,或者是要求调用者给一个空间来放这个字符串。但是当返回类型是string时,我们就不会如此小心翼翼,因为我们知道string类实现了拷贝构造函数和赋值函数。它会为我们操心空间分配和销毁的问题。所以在这里,我们直接返回"just a test"字符串是没有问题的。

接着我们对一个string对象调用c_str函数貌似也没有什么问题,因为这是string类提供给我们的功能。但是这里的关键是,我们没有将getString()的结果赋给一个string对象就直接获取其指针了,这时,系统并不会为string调用拷贝构造函数或是赋值函数,返回的string仍然只是一个临时对象的状态,它会在完成对pc的赋值后被销毁,这时其内部的数据也不会存在了。

怎么解决这个问题呢?

我们要改变c_str函数,让它不要直接返回指针,而是new一段空间来放这个字符串再返回指针吗?这样,会降低效率,且每个调用c_str函数的用户都需要操心delete指针的问题,很容易造成内存泄露。

我们要改写getString函数,重新为返回的字符串new一段空间吗?这么做显然也不合适。

这时,我们有两种比较可行的解决方法。

1.不要直接返回临时对象的指针,将临时对象先赋值给一个局部对象,再获取其指针。这样,将上例改写为

void test()
{
string str = getString();
const char *pc = str.c_str();
cout<<pc<<endl;
}

2.如果要使用临时对象的指针,将所有的使用放到一个语句里进行。这样,将上例改写为

void test()
{
cout<<getString().c_str()<<endl;
}

上面是个人愚见,欢迎大家讨论!

C++陷阱之慎用string类的更多相关文章

  1. java中的String类常量池详解

    test1: package StringTest; public class test1 { /** * @param args */ public static void main(String[ ...

  2. 跟着刚哥梳理java知识点——深入理解String类(九)

    一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码: public final class String implements java.io.Ser ...

  3. java之String类在堆栈存储机制

    String类是一个比较特殊的类,最主要的体现是它有多种创建形式,例如,String a ="abc";Sting a=new("abc");表面上看得到的结果 ...

  4. STL 的string类怎么啦?

    前言   上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对strin ...

  5. String类的详细

    String str = new String("abc")创建过程 (1) 先定义一个名为str的对String类的对象引用变量放入栈中. (2) 然后在堆中(不是常量池)创建一 ...

  6. Java之String类用法总结

    String类概述: 1.String类代表字符串.Java 程序中的所有字符串字面值(如"abc")都作为此类的实例实现. 2.String是一个final类,代表不可变的字符序 ...

  7. 标准库String类

    下面的程序并没有把String类的所有成员方法实现,只参考教程写了大部分重要的成员函数. [cpp] view plain copy #include<iostream> #include ...

  8. 自己实现简单的string类

    1.前言 最近看了下<C++Primer>,觉得受益匪浅.不过纸上得来终觉浅,觉知此事须躬行.今天看了类类型,书中简单实现了String类,自己以前也学过C++,不过说来惭愧,以前都是用C ...

  9. C++ string类的实现

    c++中string类的实现 今天面试被考到了, 全给忘记了!!!   //string类的实现 #include <iostream> #include <string.h> ...

随机推荐

  1. docker operation method note

    docker stop script #!/bin/bash CID_LIST=$(docker ps -q | xargs)if [ "$CID_LIST" = "&q ...

  2. C++Primer 第十六章

    //1.模板定义以关键字template开始,后跟一个模板参数列表,此列表不能为空.编译器用推断出的模板参数来实例化一个特定版本的函数.类型参数前必须使用class或者typename(推荐使用typ ...

  3. UEditor和CKEditor配置上传图片,视频,附件

    UEditor: http://blog.sina.com.cn/s/blog_8bb128230102v12x.html CKEditor:http://blog.sina.com.cn/s/blo ...

  4. Lintcode: Median

    Given a unsorted array with integers, find the median of it. A median is the middle number of the ar ...

  5. 设置 BitmapData 没填充部分为透明色

    默认 BitmapData 是以白色填充的 在初始化时,设定上每3,4个参数即可透明: new BitmapData(w,h,true,0) 第4个参数要为0

  6. 前端新手分析 AJAX执行顺序,数据走向

    我是一名前端的newer 在刚学习AJAX和eJS的时候,对于顺序上面有很大迷惑,现在稍微清楚了一点, 理解不对的地方,还请各位大牛帮助给我指导一下. 总的 服务器和客户端的顺序   一. 除了必要的 ...

  7. java BigInteger

    用Java来处理高精度问题,相信对很多ACMer来说都是一件很happy的事,简单易懂.用Java刷了一些题,感觉Java还不错,在处理高精度和进制转换中,调用库函数的来处理.下面是写的一些Java中 ...

  8. linux下MYSQL备份与恢复

    1.用命令实现备份 数据库备份是很重要的.如果定期做好备份,这样就可以在发生系统崩溃时恢复数据到最后一次正常的状态,把损失减小到最少.MySQLl提供了一个mysqldump命令,我们可以用它进行数据 ...

  9. C main

    #include <stdio.h> int main(int argv, char* argc[]) { printf("argv is %d", argv); // ...

  10. 玩转HTML5移动页面(动效篇)(转载)

    本文转载自: 玩转HTML5移动页面(动效篇)