zoukankan      html  css  js  c++  java
  • C++ string的内部究竟是什么样的?

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

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

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

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

    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 类的使用者来说都应该是透明的。遗憾的是,情况并不总是这样。在多线程程序中,几乎不可能安全地使用引用计数来实现。

  • 相关阅读:
    用户自定义控件
    sql 动态行转列
    sql 将表B中不存在表A的数据 插入到表A中
    C#获取键盘和鼠标操作的时间的类
    滚动条加粗和panel,gridControl结合用
    第三项任务——用例建模
    第二项任务——项目需求分析
    第一项任务:团队组建及项目启动
    实验报告(结对项目)
    实验报告(个人项目)
  • 原文地址:https://www.cnblogs.com/RioTian/p/14224419.html
Copyright © 2011-2022 走看看