我们知道,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. CALayer 图层

    // CALayer 图层属性,继承UIView都有该属性,可设置边框宽度.颜色.圆角.阴影等 UIImageView *imageView = [[UIImageView alloc]initWit ...

  2. Java基础(40):Java中的集合介绍---Collection与Map

    集合类说明及区别Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap ...

  3. Linux内核之旅 List_entry()

    #include "iostream" #define List_entry(type,member)\ (type *)(()->data)) ) using namesp ...

  4. 3D语音天气球(源码分享)——在Unity中使用Android语音服务

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3 ...

  5. sql 修改字段长度以及其他属性

    修改字段长度 语法 :alter table <表名> alter column <字段名> 新类型名(长度) alter  table  LoaneeExpand   alt ...

  6. js 获取select 中option 的个数

    //document.writeln(document.getElementById("sel").options.length); //document.writeln(docu ...

  7. -XX:+printGC

    -XX:+printGC 可以打印GC的简要信息[GC 4790K->374K(15872K), 0.0001606 secs][GC 4790K->374K(15872K), 0.000 ...

  8. OpenStack fuel-web不可用解决办法

    Contents [hide] 1 为增加一台计算节点 2 磁盘清空 3 启动占用8001端口的进程 4 启动占用5432端口的进程 为增加一台计算节点 打开fuel-web,发现无法打开,弹出ngi ...

  9. 如何在图像处理工具包ImagXpress中对图像进行捕捉、复制和粘贴

    如何在在ImagXpress中进行图像的捕捉. 复制和粘贴呢?下面详细来看一下,在多种情况下,图和实现这些操作. 捕捉屏幕图像 捕捉通过ImageXView窗口绑定的屏幕范围,以及保存到一个Image ...

  10. window7快捷键

    新建文件夹:Shift +F10  松手  shift  + w 两遍 Enter   shift+F   Enter