C++ string中的几个小陷阱,你掉进过吗?

C++开发的项目难免会用到STL的string,使用管理都比char数组(指针)方便的多,但在得心应手的使用过程中也要警惕几个小陷阱,避免我们项目出bug却迟迟找不到原因。

1.  结构体中的string赋值问题

直接通过一个例子说明,下面的例子会输出什么:


#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

struct flowRecord
{
string app_name;
struct flowRecord *next;

};

int main() {
flowRecord *fr = (flowRecord*)malloc(sizeof(flowRecord));
fr->app_name = "hello";
out << fr->app_name << endl;
return 0;
}

嗯,当然不是简单的输出“hello”了,在Linux下用g++编译后运行试试,会出现“Segmentation fault (core
dumped)”,why?问题就出在给fr指针分配内存的时候,注意这里用的是C中的malloc而不是new,如果你换成new再运行,就不会报错
了,成功的输出“hello”,那为什么malloc就不行呢?这就要看malloc()与new()的区别了,关于两者的区别是程序员面试中屡问不爽的经典面试题,所以相信一般的程序员都知道它们之间有一个非常重要的区别就是:new在分配内存时会调用默认的构造函数,而malloc不会调用。
而STL的string在赋值之前需要调用默认的构造函数以初始化string后才能使用,如赋值、打印等操作,如果使用malloc分配内存,就不会调
用string默认的构造函数来初始化结构体中的app_name字符串,因此这里给其直接赋值是错误的,应该使用new操作符。这也提示我们用C++开发程序时,就尽量使用C++中的函数,不要C++与C混合编程,导致使用混淆,比如有时候new分配的内存却用free释放。



2. c_str()函数问题

c_str()函数用于string与const char*之间的转换,也经常能用到,下面的例子你说输出啥?


#include <iostream>
#include <string>

using namespace std;

int main() {
string s = "Alexia";
const char *str = s.c_str();
cout << str << endl;
s[1] = ‘m‘;
cout << str << endl;

return 0;
}

嗯,第一个不用多说,第二个输出是“Alexia”还是“Amexia”呢?答案是后者,咋一看const char*的值应该是个常量啊,怎么还能改变值呢?哈,又是个经典的面试题:const char*, char const*, char*
const的区别是什么?老生常谈的问题,const char*与char
const*是等价的,指的是指向字符常量的指针,即指针不能变但其指向的内容可以改变,而char*
const相反,指的是常量指针,即指向可以改变但指针指向的内容不可改变。因此这里的const
char*指向的内容是可以改变的,那么为什么改变了呢?这跟str这个const char*的生命周期及string类的实现有关,string的c_str()返回的指针是由string管理的,因此它的生命期是string对象的生命期,而string类的实现实际上封装着一个char*的指针,而c_str()直接返回该指针的引用,因此string对象的改变会直接影响已经执行过的c_str()返回的指针引用。

3. 字符串字面值与标准库string不是同一种类型

直接看下面的例子:

string s("hello");
cout<<s.size()<<endl; //OK
cout<<"hello".size()<<endl; //ERROR
cout<<s+"world"<<endl; //OK
cout<<"hello"+"world"<<endl; //ERROR

可以看出两者是非常不同的,不能混淆使用。

C++ string中的几个小陷阱,你掉进过吗?,布布扣,bubuko.com

时间: 2024-12-25 13:21:22

C++ string中的几个小陷阱,你掉进过吗?的相关文章

C# 中几个小“陷阱”

每天写代码,偶尔就会有让你抓狂的时候:代码改了千百遍,蓦然回首,Bug就在灯火阑珊处……这里就列举一些容易犯错的几个小地方,以后遇到了其他的,再慢慢添加.   1. 获取程序当前运行路径   情景复现:WPF客户端程序,开机自启动后无法进入主界面,卡在初始屏(Splash Screen)   处理问题:通过日志发现加载一个icon的时候,跳了一个Bug.初始代码如下: var icon = new Icon("Images\\xxx.ico"); 很简单,貌似不会有问题,相对目录且正确

java常量池中基本数据类型包装类的小陷阱

想必大部分学过java的人都应该做过这种题目: 1 public class Test { 2 public static void main(String[] args) { 3 //第一个字符串 4 String s1="hello"; 5 6 //第二个字符串 7 String s2="hello"; 8 9 //比较s1和s2是否相同 10 System.out.println(s1==s2); 11 12 13 /** 14 * 修改变量 15 */ 16

ShardedJedisPool 中可用连接数的小bug

ShardedJedisPool中,returnBrokenResource() 及 returnResource() ,为施放资源.关闭连接的方法,若重复调用,导致 _numActive 当前活动数一直递减,会出现负数的情况. 假如在一个方法中设置了三个jedis连接,在获取第一或第二个连接时出现异常,在抛出异常或者finally中总是施放这三个资源,会导致池中的连接连续施放三次,从而变成负数. 这样会出现连接池最大连接数配置无效的情况. 以下片段代码: public class RedisU

shell中的大括号和小括号

一.小括号,园括号() 1.单小括号 () ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格. ②命令替换.等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令.有些shell不支持,如tcsh. ③用于初始化数组.如:array=(a b c d) 2.双小括号 (( ))

Java写的抓取任意网页中email地址的小程序

/* * 从网页中抓取邮箱地址 * 正则表达式:java.util.regex.Pattern * 1.定义好邮箱的正则表达式 * 2.对正则表达式预编译 * 3.对正则和网页中的邮箱格式进行匹配 * 4.找到匹配结果 * 5.通过网络程序,打通机器和互联网的一个网站的连接 */ import java.net.*; import java.util.regex.*; import java.io.*; public class EmailAddressFetch { public static

关于Linq使用过程中遇见的一些小问题的总结

1 使用First()/FirstOrDefault().Last()/LastOrDefault()方法返回序列中的第一个或者最后一个元素时,应该确保序列已经被正确排序. int[] numbers = { 3, 1, 23, 10, 5, 12, 7, 2, 4}; int first = numbers.First(); //输出3 int firstOrdered = numbers.OrderBy(it => it).First();//输出1 从示例代码可以看出,对未正确排序的序列使

iOS 开发中使用到的小技巧汇总

国庆即将来到,一个小项目也即将完成,把自己在项目中用的一些小技巧写出来,方便查找. 1,去掉分割线--动画设置透明度alpha //去掉tableView的分隔线: self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone; self.tableView.showsVerticalScrollIndicator=NO; 2. 解决cell分割线左边短20px的问题 -(void)viewDidLayoutSubviews{ i

[C#] string 与 String,大 S 与小 S 之间有关字符串的秘密(整理中...)

string 与 String,大 S 与小 S 之间有关字符串的秘密 字符串是 String 类型的对象,它的值是文本. 在内部,文本被存储为 Char 对象的顺序只读集合. C# 字符串末尾没有以 null 结尾的字符:因此 C# 字符串可以包含任意数目的嵌入式 null 字符(“\0”). 字符串的 Length 属性代表它包含的 Char 对象的数量,而不是 Unicode 字符的数量. 若要访问字符串中的各个 Unicode 码位,请使用 StringInfo 对象. 小写 strin

现有‘abcdefghijkl’12个字符,将其所有的排列按字典序进行排序,给出任意一组排列,说出这租排列在所有排列中是第几小的

题目: 现有‘abcdefghijkl’12个字符,将其所有的排列按字典序进行排序,给出任意一组排列,说出这租排列在所有排列中是第几小的 据说这道题是百度校招的一道算法题,反正我觉得我在学校的时候很可能做不出来.在学校的时候真该好好学习啊,我也逃不过毕业之后再来后悔的命运.但是,我还是要说点正能量的话, 只要知道学,什么时候都不晚.至少现在我做这道题的时候没遇到太大的困难,说明毕业之后的学习还是有很大作用的.为了我喜欢的编程,为了我喜欢的算法,继续努力! 言归正传,我看到这道题的时候,原文有这道