char * 和 std::string

1 char * 和 std::string 的区别

char * 字符串是常量字符串,不能修改;std::string 指向的字符串可以修改

实例代码如下图所示,s1 和 s2 均是常量字符串,字符串常量保存在只读数据区,是只读的,不能写,代码中注释的那两行代码会导致段错误。

s3 是字符数组,字符数组是可以修改的,std::string 类型的字符串也是可以修改的。

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

int main() {
  char *s1 = "hello";
  char *s2 = "hello";
  char s3[] = "hello";
  std::string s4 = "hello";

  printf("s1 addr = %p, s2 addr = %p, s3 addr = %p, s4 addr = %p\n", s1, s2, s3, s4.c_str());
  printf("sizeof(s1) = %d, sizeof(s3) = %d, sizeof(s4.c_str()) = %d\n", sizeof(s1), sizeof(s3), sizeof(s4.c_str()));
  // s1[1] = 'a';
  // s2[1] = 'a';
  s3[1] = 'a';
  s4[1] = 'a';
  std::cout << "s1 = " << s1 << ", s2 = " << s2 << ", s3 = " << s3 << ", s4 = " << s4 << std::endl;
  return 0;
}

代码运行之后,可以看到 s1 和 s2 是常量字符串,这两个指针指向的地址也是相同的。

从 s1,s2 的地址和 s3,s4 的地址对比可以看出,s3 和 s4 的地址相距比较近,和 s1、s2 的地址相距比较远。s1、s2 和 s3、s4 保存的段都不一样,前者保存在只读数据段,后者保存在栈,所以地址差距才会大。 

2 std::string 是深度拷贝

如下图所示, 有 3 个字符串,s1、s2 和 s3。

s2 是基于 s1 通过拷贝构造而来,将 s2[1] 赋值为 'a',然后打印 s1 和 s2,s1 仍为 "hello",s2 为 "hallo",说明 s1 和 s2 相互不影响,是深拷贝。

s3 被 s1 赋值,将 s3[1] 赋值为 'm',然后打印  s1 和 s3,s1 仍为 "hello",s3 为 "hmllo",s1 和 s3 相互没有影响。 

#include <iostream>
#include <string>

int main() {
  std::string s1 = "hello";
  std::string s2 = s1;

  std::cout << "1, s2 = " << s1 << std::endl;
  s2[1] = 'a';
  std::cout << "2, s2 = " << s2 << ", s1 = " << s1 << std::endl;

  std::string s3 = "aaa";
  s3 = s1;
  std::cout << "1, s3 = " << s3 << std::endl;
  s3[1] = 'm';
  std::cout << "2, s3 = " << s3 << ", s1 = " << s1 << std::endl;
  return 0;
}

运行结果如下:

3 std::string capacity()

如下代码,声明了一个空字符串 s1,打印出来了 s1.capacity() 是 15,也就是说 std::string 默认就会有 15 的空间。通过这样预申请空间的方式,避免了小字符串申请内存,也是一种用空间换时间的方法。如果字符串的大小不大于 15,就不会申请堆空间,如下代码可以验证。

 执行结果:

使用 gdb 调试,对 malloc 设置断点,可以查看上边的代码哪一行调用了 malloc()。

第 11 行:

字符串长度是 16,大于 15 了,需要申请内存。

第 12 行:

拷贝构造,深拷贝,长度大于 15,需要申请内存。

第 14 行:

赋值运算符,长度大于 15,需要申请内存。

第 16 行:

新创建的 s6,长度大于 15,需要申请空间。

代码第 17 行,将 s4 赋值给 s6,虽然 s4 的长度大于 15,但是当前 s6 的 capacity() 是 20,完全能够放得下 s4,所以不需要再申请空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值