c++——string详解

string

  • string简介
    • String 类
    • 成员类型
    • 迭代器(Iterator)
      • 迭代器的原理:
      • 注意事项:
      • 示例:
    • 自动类型推导auto
      • 使用场景和语法
      • 注意事项
      • 示例
  • string中的常用函数
    • 构造函数
      • npos小知识
      • 使用案例
        • 默认构造函数
        • 字符串字面值和长度构造函数
        • 复制构造函数
        • 重复字符构造函数
        • 移动构造函数(C++11及以后)
        • 区间构造函数(C++11及以后)
        • 初始化列表构造函数(C++11及以后)
        • 带分配器的构造函数
        • 示例
    • 析构函数
    • 赋值运算符重载std::string::operator=
      • 语法结构
      • 使用案例
    • 迭代器函数
    • Capacity相关函数
    • 访问字符串函数
    • 重铸函数
    • 返回C语言风格指针函数
    • 截取函数与比较函数
    • find函数

string简介

String 类

string是表示字符序列的对象, 与普通的char*不一样,本质上是一个类,内部封装了各种函数

标准字符串类通过类似于标准字节容器的接口为此类对象提供支持,但添加了专门设计用于处理单字节字符字符串的功能。

字符串类是 basic_string 类模板的实例化,它使用 char(即字节)作为其字符类型,以及其默认的 char_traits 和分配器类型(有关模板的更多信息,请参阅basic_string)。

请注意,此类处理字节与所使用的编码无关:如果用于处理多字节或可变长度字符(如 UTF-8)的序列,则此类的所有成员(如长度或大小)及其迭代器仍将根据字节(而不是实际编码字符)进行操作。

成员类型

value_type char
traits_type char_traits
allocator_type allocator
reference char&
const_reference const char&
pointer char*
const_pointer const char*
iterator a random access iterator to char (convertible to const_iterator)
const_iterator a random access iterator to const char
reverse_iterator reverse_iterator
const_reverse_iterator reverse_iterator
difference_type ptrdiff_t
size_type size_t

迭代器(Iterator)

迭代器(Iterator)是一种设计模式,用于提供一种方法来访问容器(如数组、集合、列表等)中的元素,而不暴露其底层表示。在C++中,迭代器被广泛应用于标准库中的各种容器,如 vector、list、map 等,以及其他数据结构。它们提供了一种统一的方式来遍历容器中的元素,并允许对容器中的元素进行读写操作。

迭代器的原理:

迭代器的类型名是iterator,本质上是一个类,也可以看作一个指针么,使用迭代器要加上域名比如string::iterator。

调用迭代器的函数为 .begin()返回相当于头指针的迭代器, .end()返回相当于指向尾部元素下一个位置的指针,这个不可访问数据,用来当终止条件。

迭代器实际上是一种指向容器元素的对象,它允许逐个访问容器的元素,并且支持对容器元素的操作。迭代器一般提供以下几种操作:

解引用(Dereferencing): 通过迭代器访问容器中的元素值。
递增(Incrementing): 将迭代器指向下一个元素。
比较(Comparing): 比较两个迭代器的位置关系,例如判断是否相等或大小关系。

迭代器的实现原理基于面向对象的设计,通过重载运算符来实现上述操作,例如 * 运算符用于解引用,++ 运算符用于递增迭代器。

注意事项:

失效问题: 在使用迭代器遍历容器时,若容器发生了增删操作,可能会导致迭代器失效(invalidated)。失效的迭代器不能再被使用,因此在进行插入或删除操作后,通常需要更新迭代器或者小心使用。

范围控制: 确保迭代器在有效的范围内操作,避免越界访问容器。

可变性问题: 不同类型的迭代器可能对容器的可变性有不同的影响。例如,使用 const_iterator 可以确保不修改容器元素。

迭代器类型: 不同的容器可能提供不同类型的迭代器,如正向迭代器、逆向迭代器等,应根据需要选择合适的迭代器类型。

示例:

以下是一个简单的示例,演示如何使用迭代器遍历和修改一个 vector 容器中的元素:

#include 
#include 

using namespace std;

int main() {
   
    string s = "123456789";

    // 使用迭代器遍历并输出元素
    cout << "Original vector: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
        cout << *it << " ";
    }
    cout << endl;

    // 使用迭代器修改元素
    for (string::iterator it = numbers.begin(); it != numbers.end(); ++it) {
   
        *it *= 2;
    }

    // 再次遍历输出修改后的元素
    cout << "Modified vector: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

在这个例子中,我们使用 vector 的迭代器 begin() 和 end() 来遍历容器中的元素,并且通过解引用迭代器 *it 来修改元素的值。这个例子展示了迭代器的基本用法和注意事项。

自动类型推导auto

自动类型推导(Automatic Type Deduction)是C++11引入的特性,通过关键字 auto 来实现。它允许编译器根据变量的初始化表达式推断出其类型,而无需显式地指定类型名。这种特性的引入使得代码更加简洁和易于维护,尤其是在处理复杂的模板类型时尤为有用。

使用场景和语法

在以下几种情况下,可以使用 auto 进行类型推导:

变量声明和初始化

auto x = 5; // 推导为 int
auto pi = 3.14; // 推导为 double
auto name = "John"; // 推导为 const char*

在这些示例中,编译器会根据右侧的初始化表达式推断出变量的类型。

函数返回类型推导(C++14)

auto add(int a, int b) {
   
    return a + b; // 推导为 int
}

函数的返回类型可以使用 auto,编译器会根据函数体中的返回语句推断返回类型。

迭代器和泛型编程

std::vector<int> numbers = {
   1, 2, 3, 4, 5};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
    // *it 推断为 int&
    std::cout << *it << " ";
}

在迭代器等泛型编程中,使用 auto 可以简化代码,特别是当容器的类型较复杂或是使用了模板时。

注意事项

类型推导的准确性: auto 推导的类型与初始化表达式密切相关,例如 auto x = 5; 推导为 int,而 auto y = 5.0; 推导为 double。

可读性和维护性: 尽管 auto 可以简化代码,但有时显式指定类型可以增强代码的可读性和维护性,特别是在函数签名和复杂表达式中。

初始化表达式的重要性: 类型推导依赖于变量的初始化,如果初始化表达式改变,推导出的类型也会相应改变。

避免过度使用: 在代码可读性受影响或需要强调类型时,应避免过度使用 auto。

示例

下面是一个结合了多种情况的示例:

#include 
#include 

int main() {
   
    auto num = 10; // 推导为 int
    auto name = "Alice"; // 推导为 const char*

    std::vector<double> values = {
   1.2, 3.4, 5.6};
    for (auto it = values.begin(); it != values.end(); ++it) {
   
        // *it 推导为 double&
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    auto sum = [](int a, int b) {
    return a + b; }; // 推导为 int

    return 0;
}

string中的常用函数

构造函数

在c++11中总共有这些个构造函数

default (1) string();
copy (2) string (const string& str);
substring (3) string (const string& str, size_t pos, size_t len = npos);
from c-string (4) string (const char* s);
from buffer (5) string (const char* s, size_t n);
fill (6) string (size_t n, char c);
range (7) template string (InputIterator first, InputIterator last);
initializer list (8) string (initializer_list il);
move (9) string (string&& str) noexcept;

npos小知识

npos 是C++标准库中的一个静态成员常量,通常用于表示字符串和容器类中的无效或末尾位置。具体来说:

  • 对于 std::string 类型,npos 是 std::string::npos,它表示字符串的末尾位置或者无效位置。
  • 对于 std::vector、std::deque 等容器,也有类似的静态成员常量表示末尾或无效位置。

在实际使用中,npos 的值通常是一个很大的正整数,用来表示找不到或者无效的位置。例如,对于 std::string,npos 的值通常是 std::string::npos,这个值在大多数实现中是 -1,但是它是无符号数,因此实际的二进制值是 std::string::npos。

使用案例

默认构造函数

cpp
std::string str; // 创建一个空字符串
这种形式的构造函数创建一个空的字符串对象。

字符串字面值和长度构造函数

cpp
const char* cstr = “Hello”;
std::string str(cstr); // 使用C风格字符串初始化
std::string str(cstr, 3); // 使用部分C风格字符串初始化
这种构造函数接受一个 C 风格字符串 const char* 或者一个部分C风格字符串和长度,用于初始化 std::string 对象。

复制构造函数
std::string str1("Hello");
std::string str2(str1);  // 使用另一个字符串对象初始化

这种构造函数使用同类型的另一个 std::string 对象来初始化新的对象。

重复字符构造函数
std::string str(5, 'A');  // 创建包含5个'A'字符的字符串

这种构造函数创建一个由指定数量重复字符组成的字符串。

移动构造函数(C++11及以后)
std::string str1 = "Hello";
std::string str2 = std::move(str1);  // 使用移动语义来初始化str1 可能被置为空

这种构造函数使用移动语义来初始化一个新的 std::string 对象,通常用于转移资源所有权,提高性能

你可能感兴趣的:(c++,开发语言)