【C++深度剖析教程15】经典问题解析之关于string的疑问
今天来看一下在面试笔试中经常会出错的地方。
我们先来看一个代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "12345";
const char* p = s.c_str();
cout << p << endl;
s.append("abced");
cout << p << endl;
return 0;
}
看一下这个代码,第一感觉是没有什么问题的,指针p指向了S这个字符串,那么当执行 s.append(“abced”);这句话之后,字符串S会增加“abced”这借个字符,那么打印输出的结果应该为:12345和12345abced。但是我们运行程序发现,两条打印语句都是12345.这是为什么呢?下面我们看图详细分析一下:
一开始只是字符串S指向0xFF112233这个内存空间,然后让P指向这个空间,执行这句话后:s.append(“abced”);S这个字符串变成了0x12345abced,同时这个字符串所对应的地址空间却变成了:0xFF445566,但是此时指针P依然指向之前的0xFF112233,里面的值是没有变化的,为什么出现这种情况呢?
因为:string对象维护了一个指向数据的char*指针,这个指针在程序运行阶段,有可能会发生突变。
所以那个P指针还是指向原来的0xFF112233这个地址,打印输出的内容就还是12345了。
下面再看一个程序:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char* p = "12345";
string s = "";
s.reserve(10); //分配内存大小为10
// 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
cout << s << endl;
return 0;
}
这个程序运行结果为:空!!!
为什么呢?难道对S的赋值没有成功么?我们给出分析,用C语言描述C++中的字符串,会出现一些异常,看图:
这里可以看出,m_cstr是指向字符串的内容,m_length是string类的成员变量,它指向字符串的长度,经过for循环后,我们操作的不是对象的整体,m_cstr所指向的字符串确实有了,但是m_length却依然为0,所以最后打印出来的是空,我们应该直接操作这个对象,才能让m_length随着赋值而出生存在。
我们把程序改成这样:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char* p = "12345";
string s = "";
s.reserve(10);
s = p; //直接操作对象,不要像C语言那样进行for循环赋值。
// 不要使用 C 语言中的方式操作 C++ 中的字符串
/*
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
*/
cout << s << endl;
return 0;
}
打印结果为:
这下就是我们期待的结果了。
总结一下:
-string类通过一个数据空间保存字符串数据
-string类通过一个成员变量保存当前字符串的长度
-C++开发时,尽量避免C语言的一些惯用的编程思想
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。