pointerString
前言
C语言的字符串是通过数组实现的,数组本质上又和指针无二。
那么cpp的字符串底层是否跟C语言一致
正文
1 | char ch[] = "hello world"; |
在C语言里,ch现在就= ch[0]; 象征着数组首地址。
但是string的构造我们还不清楚,所以通过编译器查看
1 |
|
原本想通过这样直接输出的,但是cout好像优化掉了&str[0]
,得到的还是整个字符串的值。
那就粗暴点用C语言的printf指定格式输出
1 | printf("%p\n", &str); |
结果是地址不同:
其实使用string的时候需要引入头文件就该知道string不简单,它也属于容器的一种,底层是通过类实现的。
再往后查看str[1]的地址:
发现str[0]和[1]直接相差1个字节,这才符合数组是由一个个char组成的。
其次我们知道C语言的字符串长度是固定的,只有动态数组才能扩容,或者说合并数组时候需要用到一块新的内存空间,string虽然有重载的办法,但是底层也是八九不离十
1 |
|
给str扩容,看看地址会不会发生改变
发现只有这个所谓的str首地址没有改变,剩下的0和1都变了,且幅度有点大,有点跟我们之前比较栈区和堆区之间地址的差异。
如果就只想看到字符串那一块的内存,可以使用c++11标准提供的两个函数
- .c_str() 得到一个const char*的指针,指向字符串的内存空间
- .data() 得到一个const char*的指针,指向字符串的内存空间
这么一看这俩方法好像是重复的,没有啥特别意义,所以在c++17标准之后统一了,只不过返回的只是个指针而不是常量指针了。
c++ 17标准
- .data() 得到的是个char*的指针了
当我们定义一个常量指针接受str.c_str()时:
能看到cs指向的地址和str[0]是一致的。
虽然.c_str()返回的是常量指针,但是如果我们想修改,还是可以通过强制转换实现,但是这种限定是很有必要的。个人没必要闲的蛋疼去玩。
且早期的之后string不要求数组以0结尾,因为string内置累加器,会自动记录长度,通过调用length方法获取。不像C语言的时候要区分strlen和sizeof的区别。但c++11之后还是要求了string也要以0结尾
结语
主要就是区分string底层和char[]存在一定区别