小心使用临时string对象的c_str()值

在这篇链接http://blog.csdn.net/while0/article/details/26291855  里看到这样的代码

const char* file_path = FileUtils::getInstance()->fullPathForFilename("hello.json").c_str();
log("external file path = %s",file_path);
rapidjson::Document d1;
std::string contentStr = FileUtils::getInstance()->getStringFromFile(file_path);
d1.Parse<0>(contentStr.c_str());
//打印JSon文件的内容
printf("%s\n",contentStr.c_str());

粗看这个代码,似乎没有问题,实际上有大问题,在我的xcode里运行,第4行的file_path变成了空字符串,为啥?

还有这个例子:

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

输出结果会为空。(有的编译器可能没问题)

两段代码的相同点是都存在没有将返回结果赋给string对象再取c_str值,而是直接通过返回的临时对象取c_str值,这样得到的c_str赋值在临时string对象析构后变为空值。

有两种比较可行的解决方法。

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

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

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

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

关于c_str(),还有下面的陷阱:

int main(){ 
    string greet("Hello, world");        
    string hi(greet);        
    char *ptr = (char *)hi.c_str();        
    ptr[0] = ‘h‘;        
    cout << hi << endl;        
    cout << greet << endl;
}
int main() { 
    string s = "Alexia"; 
    const char *str = s.c_str(); 
    cout << str << endl; 
    s[1] = ‘m‘; 
    cout << str << endl; 
    return 0; 
}

可以试试看有怎样的输出结果。

参考:

http://www.cnblogs.com/studynote/p/3476993.html

http://blog.csdn.net/song_hui_xiang/article/details/8830000

http://blog.sina.com.cn/s/blog_4e0c21cc010095hf.html

时间: 2024-12-14 09:07:44

小心使用临时string对象的c_str()值的相关文章

js中String对象slice()方法跟subString()的区别

slice() 和 substring() ECMAScript 提供了两种方法从子串创建字符串值,即 slice() 和 substring().这两种方法返回的都是要处理的字符串的子串,都接受一个或两个参数.第一个参数是要获取的子串的起始位置,第二个参数(如果使用的话)是要获取子串终止前的位置(也就是说,获取终止位置处的字符不包括在返回的值内).如果省略第二个参数,终止位就默认为字符串的长度. 与 concat() 方法一样,slice() 和 substring() 方法都不改变 Stri

JavaScript String对象常用方法

length 返回字符串的长度(字符数) var str='Hello World!'; str.length; //12 charAt() 返回指定位置的字符,第一个字符位置为0 var str='Hello World!'; str.charAt(4); //o  charCodeAt() 返回字符串第一个字符的 Unicode 编码. var str='Hello World!'; str.charAt(4); //111 concat() 用于连接两个或多个字符串.该方法没有改变原有字符

转:C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

[转] C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

String对象内存分配和基本数据类型的默认值与初始化相关问题

题目: 阅读下面代码段,给出以下代码的输出结果. public class TestFunction { static int i; public static void main(String[] args) { String str1 = "abc"; String str = "abc"; String str2 = new String("abc"); System.out.println(str1 == str2); System.ou

String 类 的c_str()函数

先看一个例子: int lines, i; int left, right; <strong><u> string strleft,</u></strong> pNode tPointerArray[MaxNum]; pNode tPointer; bool flag[MaxNum] = {false}; cin >> lines; for ( i = 0; i < lines; i++ ) { tPointer = ( pNode )ma

string 对象及其操作

标准库类型string 标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件.作为标准库的一部分,string定义在命名空间std中.接下来的示例都假定了已包含了下述代码: #include <string> using std::string; 本节描述最常用的string操作. 定义和初始化string对象 如何初始化类的对象是由类本身决定的.一个类可以定义很多种初始化对象的方式,只不过这些方式之间必须有所区别:或者是初始值的数量有所区别,或者是初

分析Java的String对象

对于Java中的String对象,个人觉得每个程序员都会思考过.学习过.研究过这个对象,因为他是面试官们的最爱.如:String s = new String("abc");,创建了几个对象.这种问题反复出现在程序员面试的过程中.下面我们对应着一些代码片段以及其的执行结果,来深入分析Java的String对象. 首先我们要注意的是String对象的处理在JDK6和JDK7中的处理是不同的.下面通过代码来分析String的三个主要方面知识. 1.常量池的存在 先看看下面代码以及执行结果:

string对象和C风格代码的混用

我们都知道可以用已下方式来初始化string对象: string  s("hello world!"); 实际上我们也可以通过这样的方式来实现: char c[] = {'h','e','l','l','o','  ','w','o','r','l','d','!','\0'}; string s = c; 但是如果数组c不是以空字符结尾的话,那么上面的赋值就是不正确的. 实际上,任何出现字符串字面值(即上面的"hello world!"这种形式)的地方都可以用以空