C++陷阱之慎用string类
我们知道,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类的更多相关文章
- java中的String类常量池详解
test1: package StringTest; public class test1 { /** * @param args */ public static void main(String[ ...
- 跟着刚哥梳理java知识点——深入理解String类(九)
一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码: public final class String implements java.io.Ser ...
- java之String类在堆栈存储机制
String类是一个比较特殊的类,最主要的体现是它有多种创建形式,例如,String a ="abc";Sting a=new("abc");表面上看得到的结果 ...
- STL 的string类怎么啦?
前言 上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对strin ...
- String类的详细
String str = new String("abc")创建过程 (1) 先定义一个名为str的对String类的对象引用变量放入栈中. (2) 然后在堆中(不是常量池)创建一 ...
- Java之String类用法总结
String类概述: 1.String类代表字符串.Java 程序中的所有字符串字面值(如"abc")都作为此类的实例实现. 2.String是一个final类,代表不可变的字符序 ...
- 标准库String类
下面的程序并没有把String类的所有成员方法实现,只参考教程写了大部分重要的成员函数. [cpp] view plain copy #include<iostream> #include ...
- 自己实现简单的string类
1.前言 最近看了下<C++Primer>,觉得受益匪浅.不过纸上得来终觉浅,觉知此事须躬行.今天看了类类型,书中简单实现了String类,自己以前也学过C++,不过说来惭愧,以前都是用C ...
- C++ string类的实现
c++中string类的实现 今天面试被考到了, 全给忘记了!!! //string类的实现 #include <iostream> #include <string.h> ...
随机推荐
- Silverlight Popup Bubble
控件下载地址: http://www.pudn.com/downloads217/sourcecode/others/detail1023372.html silverlight工程引入Liquid. ...
- PostgreSQL/bin
pg_receivexlog pg_receivexlog—以流的方式从一个PostgreSQL集簇得到事务日志 pg_receivexlog被用来从一个运行着的PostgreSQL集簇以流的方式得到 ...
- Lintcode: Count of Smaller Number
Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 1 ...
- !! 浅谈Java学习方法和后期面试技巧
浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...
- HDU 1728 逃离迷宫(BFS)
Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有 ...
- 使用streaming window函数统计用户不同时间段平均消费金额等指标
场景 现在餐厅老板已经不满足仅仅统计历史用户消费金额总数了,他想知道每个用户半年,每个月,每天,或者一小时消费的总额,来店消费的次数以及平均金额. 给出的例子计算的是每5秒,每30秒,每1分钟的用户消 ...
- 使用Ef查询出现的问题The cast to value type 'System.Boolean' failed because the materialized value is null.的解决方法
把值类型的系统.布尔的失败是因为物化值是null.结果类型的泛型参数或查询必须使用可空类型. 解决方法: 请确保你查询中的字段值不为空或者做为空判断
- sql 查看 锁定的表 或者 未提交 的事务
--查看锁定的 表select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sy ...
- Linux下用SCP无需输入密码传输文件
在Linux环境下,两台主机之间传输文件一般使用scp命令,通常用scp命令通过ssh获取对方linux主机文件的时候都需要输入密码确认. 不过通过建立信任关系,可以实现不输入密码. 这里假设A的IP ...
- small details
1.操作数据时,一般能入库就入库,或者用xml文件,用文件操作比较复杂