今天来看一下在面试笔试中经常会出错的地方。
我们先来看一个代码:

#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。但是我们运行程序发现(纠错:使用gcc 4.4.7版本编译器),两条打印语句都是12345.这是为什么呢?下面我们看图详细分析一下:

一开始只是字符串S指向0xFF112233这个内存空间,然后让P指向这个空间,执行这句话后:s.append(“abced”);S这个字符串变成了0x12345abced,同时这个字符串所对应的地址空间却变成了:0xFF445566,但是此时指针P依然指向之前的0xFF112233,里面的值是没有变化的,为什么出现这种情况呢?

因为:string对象维护了一个指向数据的char*指针,这个指针在程序运行阶段,有可能会发生突变。
所以那个P指针还是指向原来的0xFF112233这个地址,打印输出的内容就还是12345了。

纠错:

  • 针对上述的说明,有网友提出质疑,在vs2013上运行结果就是12345和12345abced。我也做了实验,在vs2017上运行结果也是12345和12345abced。而在我的Linux中,使用gcc
    4.4.7版本编译器,运行结果就是12345和12345。使用gcc 7.3.0 编译器,就得到12345和12345abced 这个结果。很明显,这与编译器实现有关,比较新版本的编译器可以得到正常的运行结果。
  • 很明显,我一开始的分析,也是有一些错误的。string对象维护了一个指向数据的char* 指针,这个指针在程序的运行阶段是有可能发生突变,也有可能不发生突变。比较新的编译器编译都没有发生突变,说明比较新的编译器解决了那个bug。
  • 在我下面的评论中,我之前说可以从另一个角度理解为什么打印结果一样,就是const,这种说法也是不对的,const修饰的变量,则该变量不能出现在赋值符号的左边,不能被直接改变,但是可以被间接改变。

下面再看一个程序:

#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语言,数据结构等技术问题。

【C++深度剖析教程15】经典问题解析之关于string的疑问相关推荐

  1. 【C++深度剖析教程39】实现C++数组类模板

    上一篇文章在那个学习了多参数类模板与特化的分析:点击链接查看上一篇文章:类模板深度剖析 本篇文章学习记录: 数值型模板参数 实现C++数组类模板 1.模板中的数值型参数 模板参数可以是数值型参数.也就 ...

  2. 【C++深度剖析教程14】经典问题解析三之关于赋值的疑问

    今天我们来总结一下,之前所学C++中所遇到的一些经典的问题. 第一个疑问是: -什么时候需要重载赋值操作符 -编译器是否提供默认的赋值操作? 解答: *编译器为每个类默认重载了赋值操作符 *默认的赋值 ...

  3. 【C++深度剖析教程2】C++经典问题解析之二 this指针与成员函数

    隐藏的this指针,所有对象共享类的成员函数 写一篇博客花费时间虽然长,但是却让你对内容的记忆尤为深刻,尤其是你对它的态度.记录菜鸟的成长日记,也希望同为菜鸟的你们与我一起共同进步!!现在分享的是C+ ...

  4. 【C++深度剖析教程1】C++中的经典问题解析-c++中的对象的构造顺序与析构顺序

    c++中的对象的构造顺序与析构顺序 问题一 当程序中存在多个对象时,如何确定这些对象的析构顺序? 一.单个函数创建时构造函数的调用顺序 1.调用父类的构造过程 2.调用成员变量的构造函数(调用顺序与声 ...

  5. 【C++深度剖析教程25】继承中的构造与析构

    今天来学习C++中继承的构造与析构,有兴趣一起学习的加qq:1126137994 1.问题 如何初始化父类成员?父类构造函数与子类构造函数有什么关系? 子类对象是如何构造的? 子类中可以定义构造函数 ...

  6. 【C++深度剖析教程38】类模板深度剖析

    加qq1126137994 微信:liu1126137994 一起学习更多技术!!! 1.多参数类模板 类模板可以定义任意多个不同的类型参数 类模板可以被特化: 指定类模板的特定实现 部分类型参数必须 ...

  7. 【C++的深度剖析教程20】类型转换函数上

    今天来学习类型转换函数. 一回顾 我们学习C语言的时候,都知道,标准的数据类型之间,是可以做类型的转换的.分为隐式类型转换和强制类型转换.那么强制类型转换呢,比较简单.但是隐式类型转换,却存在诸多问题 ...

  8. 【C++深度剖析教程9】初探C++标准库

    在这之前,我写的C++程序不能叫做标准的C++程序,因为里面写的大多数还带有C语言的影子.今天我们来学习C++标准库. 首先看一下例子:操作符<<的原生意义是按位左移.那么我们重载这个操作 ...

  9. 【C++深度剖析教程7】C++之类中的函数重载

    函数重载的回顾(接上一篇文章): 函数重载的本质为相互独立的不同的函数 C++中通过函数名和函数参数确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的成员 ...

最新文章

  1. bert简介_BERT简介
  2. Linq的优点以及注意事项
  3. jQuery 源码解析笔记(一)
  4. 用汇编的眼光看C++(之const属性)
  5. vue2.0 keep-alive 缓存页面数据
  6. C语言课程设计|通讯录管理系统(含完整代码)
  7. 51单片机驱动TM1640实现多个LED灯控制
  8. Gartner的企业信息管理EIM模型
  9. pixhawk硬件设计粗略解析
  10. VS上位机开发——串口助手
  11. 视频直播本地测试服务器搭建
  12. Unity shader系列:好用的IDE--JetBrain Rider
  13. 谷歌hosts laod
  14. gc System.gc() fullGC
  15. 计算机 竞赛 甘肃,甘肃省第三届创新杯计算机应用能力大赛获奖名单
  16. java markdown转word_Markdown 格式如何转换成 Word?
  17. C++中经典的垃圾回收算法
  18. 一夜大涨3230亿,苹果市值等于2.5个阿里或16个京东
  19. 男人的责任--Cinderella Man
  20. 熊猫关闭服务器微信,熊猫直播开始关闭服务器:App已在苹果应用商店下架

热门文章

  1. 31.javaweb简介
  2. P2896 [USACO08FEB]一起吃饭Eating Together 解题报告
  3. 转:Fiddler抓包工具总结
  4. PHP漏洞全解(二)-命令注入攻击
  5. cdoj 1246 每周一题 拆拆拆~ 分解质因数
  6. linux下常用FTP命令
  7. 查看WEB服务器的连接数
  8. 思维探索者:从问题到答案的思维过程 像侦探一样思考
  9. CSS命名规范(建议版)(转)
  10. C# ASP.NET MVC 微信和支付宝H5支付开发及Demo