admin管理员组文章数量:1446760
【C++指南】string(二):深入探究 C++ `basic
引言
在第一篇文章中【C++指南】string(一):string从入门到掌握,我们对 C++ 中 string
的起源、basic_string
模板类以及相关字符串类型有了初步的了解。
本文将深入剖析 basic_string
的成员变量、默认成员函数、迭代器、容量管理、修改操作等各类成员函数,详细介绍它们的使用方法、功能特点以及遵循的规则。
basic_string
的成员变量
内部结构概述
basic_string
类模板通常包含几个关键的成员变量来管理字符串数据,虽然具体实现可能因编译器而异,但一般会有以下几个核心部分:
- 字符存储指针:指向存储字符串字符的动态分配内存区域。
- 字符串长度:表示当前字符串中实际字符的数量。
- 容量:表示当前分配的内存空间能够容纳的字符数量(包括字符串结束符)。
示例代码推测成员变量
虽然标准库没有公开 basic_string
的成员变量,但我们可以通过模拟实现来推测其可能的结构:
template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT>>
class basic_string {
private:
CharT* _data; // 字符存储指针
size_t _size; // 字符串长度
size_t _capacity; // 容量
// 其他可能的成员变量和实现细节
};
默认成员函数
构造函数
basic_string
提供了多种构造函数重载,以满足不同的初始化需求。
- 默认构造函数:创建一个空字符串。
#include <iostream>
#include <string>
int main() {
std::string str; // 默认构造,创建空字符串
std::cout << "Empty string: " << str << std::endl;
return 0;
}
- 带字符串字面量的构造函数:使用字符串字面量初始化字符串。其中这个构造函数是日常中最常用的
std::string str("Hello, World!");
std::cout << "Initialized with literal: " << str << std::endl;
- 带重复字符的构造函数:使用指定字符重复多次初始化字符串。
std::string str(5, 'a'); // 初始化为 "aaaaa"
std::cout << "Repeated characters: " << str << std::endl;
- 拷贝构造函数:创建一个新字符串,其内容是另一个字符串的副本。
std::string original("Original");
std::string copy(original);
std::cout << "Copied string: " << copy << std::endl;
析构函数
析构函数负责在字符串对象生命周期结束时释放其占用的内存资源,防止内存泄漏。在使用 std::string
时,我们无需手动管理内存,析构函数会自动完成这些工作。
{
std::string str("Temporary");
// 当 str 离开作用域时,析构函数自动调用
}
赋值运算符重载
赋值运算符用于将一个字符串的值赋给另一个字符串。
std::string source("Source");
std::string destination;
destination = source;
std::cout << "Assigned string: " << destination << std::endl;
迭代器
迭代器类型
basic_string
支持多种迭代器类型,用于遍历字符串中的字符。
- 正向迭代器:
begin()
和end()
分别返回指向字符串起始和结束位置(最后一个字符的下一个位置)的迭代器。
std::string str("Iterate");
for (auto it = str.begin(); it != str.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
- 反向迭代器:
rbegin()
和rend()
分别返回指向字符串末尾和起始位置(第一个字符的前一个位置)的反向迭代器。
for (auto rit = str.rbegin(); rit != str.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
- 常量迭代器:
cbegin()
、cend()
、crbegin()
和crend()
用于遍历常量字符串,确保不会修改字符串内容。
const std::string constStr("Constant");
for (auto cit = constStr.cbegin(); cit != constStr.cend(); ++cit) {
std::cout << *cit << " ";
}
std::cout << std::endl;
迭代器的使用规则
- 迭代器可以进行递增(
++
)和递减(--
)操作,用于移动到下一个或前一个字符位置。 - 可以使用
*
运算符解引用迭代器,获取当前指向的字符。 - 在使用迭代器时,要确保迭代器的有效性,避免越界访问。
容量管理
容量相关函数
size()
和length()
:返回字符串中当前存储的字符个数,这两个函数功能相同。- 一般我们都会选择使用size函数,因为size函数在C++中的其他容器中也是通用的,只有length函数是因为历史发展原因string所独有的
std::string str("Capacity");
std::cout << "Size: " << str.size() << ", Length: " << str.length() << std::endl;
capacity()
:返回字符串当前已分配的内存空间能够容纳的字符个数,通常大于或等于size()
。
std::cout << "Capacity: " << str.capacity() << std::endl;
reserve()
:预先分配一定大小的内存空间,避免在字符串增长过程中频繁的内存重新分配,提高性能。
str.reserve(20);
std::cout << "Reserved capacity: " << str.capacity() << std::endl;
resize()
:改变字符串的长度。- 若新长度小于原长度,则会截断字符串;
- 若新长度大于原长度,会在字符串末尾填充指定字符(默认为空字符);
- 若新长度大于string容量,则会扩容,并在补充的部分添加指定字符
str.resize(3);
std::cout << "Resized string: " << str << std::endl;
str.resize(5, 'x');
std::cout << "Resized and filled: " << str << std::endl;
容量管理规则
- 当字符串长度超过当前容量时,
basic_string
会自动重新分配更大的内存空间,并将原有字符复制到新的内存区域。 reserve()
只是预先分配内存,不会改变字符串的长度。resize()
会直接改变字符串的长度,可能会导致内存重新分配。
修改操作
插入操作
一般我们用的最多的还是 operator+=,相当于尾插,而insert和erase非必要尽量不用,因为前插涉及到挪动数据,会存在效率的问题
insert()
函数用于在字符串的指定位置插入字符或字符串。
std::string str("Insert");
str.insert(2, "abc"); // 在位置 2 插入 "abc"
std::cout << "Inserted string: " << str << std::endl;
删除操作
erase()
函数用于删除字符串中指定位置或范围的字符。
str.erase(2, 3); // 从位置 2 开始删除 3 个字符
std::cout << "Erased string: " << str << std::endl;
追加操作
push_back()
:在字符串末尾添加一个字符。
str.push_back('!');
std::cout << "Pushed back: " << str << std::endl;
append()
和operator+=
:用于在字符串末尾追加字符或字符串。
str.append(" World");
std::cout << "Appended string: " << str << std::endl;
str += "!";
std::cout << "Appended with +=: " << str << std::endl;
修改操作规则
- 插入和删除操作可能会导致内存重新分配和字符移动,影响性能。
- 追加操作通常比插入操作更高效,因为它只在字符串末尾进行操作。
其他相关函数
查找函数
find()
:在字符串中查找指定的字符或子串,返回其第一次出现的位置,如果未找到则返回std::string::npos
。
std::string str("Find me");
size_t pos = str.find("me");
if (pos != std::string::npos) {
std::cout << "Found at position: " << pos << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
rfind()
:从字符串末尾开始查找,返回最后一次出现的位置。
替换函数
replace()
用于将字符串中指定范围的字符替换为其他字符或子串。
str.replace(0, 4, "Replace");
std::cout << "Replaced string: " << str << std::endl;
比较函数
compare()
用于比较两个字符串的大小,返回一个整数表示比较结果。
std::string str1("Hello");
std::string str2("World");
int result = str1pare(str2);
if (result < 0) {
std::cout << str1 << " is less than " << str2 << std::endl;
} else if (result > 0) {
std::cout << str1 << " is greater than " << str2 << std::endl;
} else {
std::cout << str1 << " is equal to " << str2 << std::endl;
}
总结
本文详细介绍了 C++ basic_string
的成员变量、默认成员函数、迭代器、容量管理、修改操作以及其他相关函数。通过深入了解这些内容,我们可以更加灵活和高效地使用 std::string
及其相关类型。在实际编程中,合理运用这些函数可以提高代码的可读性和性能,避免常见的错误和问题。
后续我们还将进一步探讨 basic_string
的底层实现和一些高级应用场景。
本文标签: C指南string(二)深入探究 C basic
版权声明:本文标题:【C++指南】string(二):深入探究 C++ `basic 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1748278083a2836692.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论