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. 分别是运算符左侧和右侧的值 ↩︎↩︎
相关文章
|
6天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
21 2
|
12天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
40 5
|
19天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
49 4
|
20天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
46 4
|
2月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
58 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
2月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
34 2
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
28 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
25 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
22 1
|
2月前
|
数据可视化 Java
让星星月亮告诉你,通过反射创建类的实例对象,并通过Unsafe theUnsafe来修改实例对象的私有的String类型的成员属性的值
本文介绍了如何使用 Unsafe 类通过反射机制修改对象的私有属性值。主要包括: 1. 获取 Unsafe 的 theUnsafe 属性:通过反射获取 Unsafe类的私有静态属性theUnsafe,并放开其访问权限,以便后续操作 2. 利用反射创建 User 类的实例对象:通过反射创建User类的实例对象,并定义预期值 3. 利用反射获取实例对象的name属性并修改:通过反射获取 User类实例对象的私有属性name,使用 Unsafe`的compareAndSwapObject方法直接在内存地址上修改属性值 核心代码展示了详细的步骤和逻辑,确保了对私有属性的修改不受 JVM 访问权限的限制
56 4