在C语言中,有两种方式表示字符串:

  • 一种是用字符数组来容纳字符串,例如char str[10] = "abc",这样的字符串是可读写的;
  • 一种是使用字符串常量,例如char *str = "abc",这样的字符串只能读,不能写。

两种形式总是以\0作为结束标志。

C++ string 与它们在C语言中的前身截然不同。首先,也是最重要的不同点,C++ string 隐藏了它所包含的字符序列的物理表示。程序设计人员不必关心数组的维数或\0方面的问题。

string 在内部封装了与内存和容量有关的信息。具体地说,C++ string 对象知道自己在内存中的开始位置、包含的字符序列以及字符序列长度;当内存空间不足时,string 还会自动调整,让内存空间增长到足以容纳下所有字符序列的大小。

C++ string 的这种做法,极大地减少了C语言编程中三种最常见且最具破坏性的错误:

  • 数组越界;
  • 通过未被初始化或者被赋以错误值的指针来访问数组元紊;
  • 释放了数组所占内存,但是仍然保留了“悬空”指针。

C++ 标准没有定义 string 类的内存布局,各个编译器厂商可以提供不同的实现,但必须保证 string 的行为一致。采用这种做法是为了获得足够的灵活性。

特別是,C++ 标准没有定义在哪种确切的情况下应该为 string 对象分配内存空间来存储字符序列。string 内存分配规则明确规定:允许但不要求以引用计数(reference counting)的方式实现。但无论是否采用引用计数,其语义都必须一致。

C++ 的这种做法和C语言不同,在C语言中,每个字符型数组都占据各自的物理存储区。在 C++ 中,独立的几个 string 对象可以占据也可以不占据各自特定的物理存储区,但是,如果采用引用计数避免了保存同一数据的拷贝副本,那么各个独立的对象(在处理上)必须看起来并表现得就像独占地拥有各自的存储区一样。例如:

// #include<bits/stdc++.h>
#include <iostream>
#include <string>
using namespace std; int main() {
string s1("12345");
string s2 = s1;
cout << (s1 == s2) << endl;
s1[0] = '6';
cout << "s1 = " << s1 << endl; // 62345
cout << "s2 = " << s2 << endl; // 12345
cout << (s1 == s2) << endl; return 0;
}

在 GCC 下的运行结果:

1
s1 = 62345
s2 = 12345
0

只有当字符串被修改的时候才创建各自的拷贝,这种实现方式称为写时复制(copy-on-write)策略。当字符串只是作为值参数(value parameter)或在其他只读情形下使用,这种方法能够节省时间和空间。

不论一个库的实现是不是采用引用计数,它对 string 类的使用者来说都应该是透明的。遗憾的是,情况并不总是这样。在多线程程序中,几乎不可能安全地使用引用计数来实现。

C++ string的内部究竟是什么样的?的更多相关文章

  1. Java 1.7.0_06中String类内部实现的一些变化【转】

    原文链接: java-performance 翻译: ImportNew.com- 夏千林译文链接: http://www.importnew.com/7656.html ChangeLog: 201 ...

  2. 关于JAVA中的String的使用与连接(转)

    JAVA中的String连接性能 Java中的String是一个非常特殊的类,使它特殊的一个主要原因是:String是不可变的(immutable).           String的不可变性是Ja ...

  3. String的内存模型,为什么String被设计成不可变的

    String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...

  4. 从template到DOM(Vue.js源码角度看内部运行机制)

    写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...

  5. Java中String连接性能的分析【转】

    [转]http://www.blogjava.net/javagrass/archive/2010/01/24/310650.html 总结:如果String的数量小于4(不含4),使用String. ...

  6. String为什么是不可变的?

    前几天一个面试被问到String为什么是不可变的?, 自我感觉当时回答的不太理想, 事后总结一下 不可变的是什么 我们谈论的String不可变, 指的是字符串的值不可变 例: String s = & ...

  7. JavaScript内部原理实践——真的懂JavaScript吗?(转)

    通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解. 但 ...

  8. 【C++探索之旅】第二部分第一课:面向对象初探,string的惊天内幕

    内容简单介绍 1.第二部分第一课:面向对象初探.string的惊天内幕 2.第二部分第二课预告:掀起了"类"的盖头来(一) 面向对象初探,string的惊天内幕 上一课<[C ...

  9. Spring Boot源码探索——自动配置的内部实现

    前面写了两篇文章 <Spring Boot自动配置的魔法是怎么实现的>和 <Spring Boot起步依赖:定制starter>,分别分析了Spring Boot的自动配置和起 ...

随机推荐

  1. pandas入门使用

    一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...

  2. PHP代码审计分段讲解(9)

    22 弱类型整数大小比较绕过 <?php error_reporting(0); $flag = "flag{test}"; $temp = $_GET['password' ...

  3. 题解-MtOI2019 幽灵乐团

    题面 MtOI2019 幽灵乐团 给定 \(p\),\(Cnt\) 组测试数据,每次给 \(a,b,c\),求 \[\prod_{i=1}^a\prod_{j=1}^b\prod_{k=1}^c\le ...

  4. Linux 上安装 mysql

    1.通过 yum 命令安装 mysql 可以先通过 yum list |grep mysql 方式查看有哪些版本的 mysql 2.安装 mysql yum install mysql-server ...

  5. html文本域textarea高度自增、自动换行

    文本域自动换行.高度自增,采用以下方式: html: <textarea rows="1" class="answerTextArea" maxlengt ...

  6. 四、Jmeter安装插件

    Jmeter安装插件方法和使用 1-下载Jmeter管理jar包 下载地址:https://jmeter-plugins.org/install/Install/ 2-点击下载 plugins-man ...

  7. Kubernetes【K8S】(四):资源控制器

    什么是控制器 ​ Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为. 控制器类型 ReplicationController和Rep ...

  8. tomcat中配置jndi数据库源

    tomcat添加依赖 lib目录下添加依赖mysql-connector-java-8.0.16 配置数据源 介绍两种方法:tomcat中配置或web应用中配置 tomcat/conf/context ...

  9. html 08-HTML5详解(二)

    08-HTML5详解(二) #本文主要内容 拖拽 历史 地理位置 全屏 #拖拽 如上图所示,我们可以拖拽博客园网站里的图片和超链接. 在HTML5的规范中,我们可以通过为元素增加 draggable= ...

  10. PHP MySQL 快速导入10万条数据

    项目背景 数据来源:所有数据均为外部导入,最大数据量在10w+ 输出数据:导出经过业务处理之后的数据 使用框架:fastadmin 涉及的问题: 1.数据读取 2.数据保存 使用数据:10w+ 解决方 ...