C++string类

简介: C++string类

📟作者主页:慢热的陕西人

🌴专栏链接:C++

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

本博客主要内容讲解了C++中的string类以及类内的一些常用函数

C++string类


Ⅰ. 为什么要学习string类

首先我们在C语言中有字符串的概念,是一些以\0结尾的字符的集合,而且C语言中也有很多和字符串相关的函数例如:strstr等,但是C语言中是将这些函数和字符串是分离开来的,这不符面向对象变成的思想,而且空间管理是交给用户自己来处理,非常容易出现越界问题。所以在C++中将字符串和字符串相关的函数集成在一个类里面,提高编程效率。

Ⅱ. 标准库中的string类

Ⅱ. Ⅰ. string类的了解

这里首先附上string类的文档string - C++ Reference (nonplussing)

  • 字符串是表示字符序列的类
  • 标准的字符串类提供了对此类对象的支持,其接口类似于标准字容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性
  • string类是使用char(即作为它的字符类型,使用它的默认char_traitsallocator(分配器)类型(关于模板的更多信 息,请参阅basic_string)
  • string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traitsallocator(分配器)作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  • 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-81)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作总结:
  • string是表示字符串的字符串类
  • 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
  • string在底层实际是:basic_string模板类的别名,typedef basic_string string
  • 不能操作多字节或者变长字符的序列

Ⅱ. Ⅱ. string类中常用接口说明

①string类对象的常见构造:

当然库中不止以下这些可以点击下面的constuct链接详细阅读。

(construct)函数名称 功能说明
string() Constructs an empty string, with a length of zero characters.
string (const string& str); Constructs a copy of str.(拷贝构造)
string (size_t n, char c); Fills the string with n consecutive copies of character c.
string (const char* s); Copies the null-terminated character sequence (C-string) pointed by s

例如:

void Teststring()
{
  string s1; // 构造空的string类对象s1
  string s2("hello bit"); // 用C格式字符串构造string类对象s2
  string s3(s2); // 拷贝构造s3
}

②string类对象的容量操作:

函数名称 功能说明
size Returns the length of the string, in terms of bytes(我们更常用这个相比于length2
length Returns the length of the string, in terms of bytes
capacity Returns the size of the storage space currently allocated for the string, expressed in terms of bytes
reserve Requests that the string capacity be adapted to a planned change in size to a length of up ton characters
clear Erases the contents of the string, which becomes an empty string (with a length of 0 characters).
resize Resizes the string to a length of n characters.
empty Returns whether the string is empty (i.e. whether its length is 0).

注意:


  • clear()只是将string中有效字符清空,不改变底层空间大小。
  • resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
  • reserve(size_t res_arg = 0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小
void Teststring1()
{
  // 注意:string类对象支持直接用cin和cout进行输入和输出
  string s("hello, bit!!!");
  cout << s.size() << endl;
  cout << s.length() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
  // 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
  s.clear();
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  // 将s中有效字符个数增加到10个,多出位置用'a'进行填充
  // “aaaaaaaaaa”
  s.resize(10, 'a');
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  // 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
  // "aaaaaaaaaa\0\0\0\0\0"
  // 注意此时s中有效字符个数已经增加到15个
  s.resize(15);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
  // 将s中有效字符个数缩小到5个
  s.resize(5);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
}

③string类对象的访问及遍历操作

函数名称 功能说明
operator[ ] Returns a reference to the character at position pos in the string.
begin + end begin: Returns an iterator pointing to the first character of the string. end: Returns an iterator pointing to the past-the-end character of the string.
rbegin + rend rbegin: Returns a reverse iterator pointing to the last character of the string. rend: Returns a reverse iterator pointing to the theoretical element preceding the first character of the string
范围for C++11支持更简洁的范围for的新遍历方式(底层还是迭代器(iterator))

范围for例子:

int arr[5] = {10, 20, 30, 40, 50};
for (int x : arr) {
    // 打印每一个元素
    std::cout << x << " ";
}

访问元素及遍历例子:

string s("hello xupt");
  // 3种遍历方式:
  // 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,
  // 另外以下三种方式对于string而言,第一种使用最多
  // 1. for+operator[]
  for (size_t i = 0; i < s.size(); ++i)
    cout << s[i] << endl;
  // 2.迭代器
  string::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it << endl;
    ++it;
  }
  // string::reverse_iterator rit = s.rbegin();
  // C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
  auto rit = s.rbegin();
  while (rit != s.rend())
    cout << *rit << endl;
  // 3.范围for
  for (auto ch : s)
    cout << ch << endl;

④string类对象的修改操作:

函数名称 功能说明
push_back Appends character c to the end of the string, increasing its length by one.
append Extends the string by appending additional characters at the end of its current value:
operator+= Extends the string by appending additional characters at the end of its current value:
c_str Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
find + npos find: Searches the string for the first occurrence of the sequence specified by its arguments. npos :Maximum value for size_tstatic const size_t npos = -1;
rfind Searches the string for the last occurrence of the sequence specified by its arguments.
substr Returns a newly constructed string object with its value initialized to a copy of a substring of this object.

注意:

  • 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  • 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好(因为扩容是需要一定的时间代价的,提前扩容的话,就可以避免反复扩容的情况,从而达到节省时间的目的)。
string str;
  str.push_back(' ');   // 在str后插入空格
  str.append("hello");  // 在str后追加一个字符"hello"
  str += 'b';           // 在str后追加一个字符'b'   
  str += "it";          // 在str后追加一个字符串"it"
  cout << str << endl;
  cout << str.c_str() << endl;   // 以C语言的方式打印字符串
  // 获取file的后缀
  string file("string.cpp");
  size_t pos = file.rfind('.');
  string suffix(file.substr(pos, file.size() - pos));
  cout << suffix << endl;
  // npos是string里面的一个静态成员变量
  // static const size_t npos = -1;
  // 取出url中的域名
  string url("http://www.cplusplus.com/reference/string/string/find/");
  cout << url << endl;
  size_t start = url.find("://");
  if (start == string::npos)
  {
    cout << "invalid url" << endl;
    return;
    }

⑤string类非成员函数

函数 功能说明
operator+3 Returns a newly constructed string object with its value being the concatenation of the characters in lhs4 followed by those of rhs.4
operator>> Extracts a string from the input stream is, storing the sequence in str, which is overwritten (the previous value of str is replaced).
operator<< Inserts the sequence of characters that conforms value of str into os.
getline Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).
relational operators Performs the appropriate comparison operation between the string objects lhs and rhs.

⑥vs和g++下string结构的说明

注意:下述结构都是在32位平台下验证的。

  • vs下的string结构:string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间:
  • 当字符串长度小于16时,使用内部固定的字符数组来存放
  • 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{   // storage for small buffer or pointer to larger one
  value_type _Buf[_BUF_SIZE];
  pointer _Ptr;
  char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
  • 这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内 部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。
    其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量
    最后:还有一个指针做一些其他事情。
    故总共占16+4+4+4=28个字节。
  • g++下string的结构G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指 针将来指向一块堆空间,内部包含了如下字段:
  • 空间总大小
  • 字符串有效长度
  • 引用计数
struct _Rep_base
{
 size_type _M_length;
 size_type _M_capacity;
 _Atomic_word _M_refcount;
};
  • 指向堆空间的指针,用来存储字符串.

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正


  1. 是一种字符编码方式详细了解可查看这个文章Unicode、UTF-8、UTF-16 终于懂了 - 知乎 ↩︎
  2. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。 ↩︎
  3. 尽量少用,因为传值返回,会导致拷贝效率低 ↩︎
  4. 分别是运算符左侧和右侧的值 ↩︎↩︎
相关文章
|
1天前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
1天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
1天前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
1天前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
3天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
3天前
|
C++
模拟实现c++中的string
模拟实现c++中的string
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
70 19
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
51 13
|
1月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
53 5
|
1月前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
41 5