跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ string 类详解:初始化、遍历与常用函数

综述由AI生成C++ 标准库中 string 类的核心功能。内容包括 string 的三种初始化方式(默认、直接构造、拷贝构造),以及三种遍历方法(下标访问、范围 for 循环、迭代器)。此外,还讲解了 string 的容量管理函数(如 capacity、reserve、clear、empty)和常用成员函数(如 operator+=、push_back、append、substr、find、replace、getline)。文章通过代码示例展示了各函数的具体用法及运行结果,帮助读者掌握 string 类的基本操作与性能特性。

栈溢出发布于 2026/3/26更新于 2026/5/2424 浏览

注意:在使用 string 类时,必须包含头文件 #include <string>。

一、string 的初始化与遍历

1. string 的初始化

string 支持多种初始化方式,这里介绍常用的三种,同时 string 也支持 cin 输入与 cout 输出。

1.1 默认初始化(创建一个空字符串 "")

语法形式: string s1;

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1;
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

1.2 直接构造(显式调用构造函数)

语法形式: string(const char* s);

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("Hello world");
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

1.3 拷贝构造(利用已有的 string 对象创建一个副本)

语法形式: string(const string& str);

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1;
    cin >> s1;
    string s2(s1);
    cout << s2 << endl;
    return 0;
}

运行结果: 文章配图

2. string 的遍历

2.1 下标访问
2.1.1 size() 函数与 length() 函数

基本用法: size() 与 length() 都返回字符串中字符的个数(即字节数,不包括末尾隐藏的 \0)。

语法形式: size_t size() const; size_t length() const;

区别: length() 在 C++ 早期是作为独立的字符串处理工具设计的,而 size() 是后来 C++ 引入了 STL(标准模板库),规定所有的容器都必须提供一个统一的接口来获取元素个数。为了让 string 也能融入这个体系,使其像一个容器一样工作,就增加了 size(),推荐使用 size()。

使用:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    cout << s1.size() << endl;
    cout << s1.length() << endl;
    return 0;
}

运行结果: 文章配图

2.1.2 operator[]

其实 string 在底层是一个类,因此重载了 [],以便我们读取/修改 string 中的字符。

语法形式: char& operator[](size_t pos); const char& operator[](size_t pos) const;

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    cout << s1[5] << endl; // 访问下标为 5 的元素
    s1[6] = 'M';           // 修改下标为 6 的元素
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

如果访问的下标超过了元素个数,会发生什么?编译器可能会报错或读取一个垃圾字符。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    cout << s1[1000] << endl;
    return 0;
}

运行结果: 文章配图

2.1.3 下标遍历

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    for (int i = 0; i < s1.size(); i++) {
        cout << s1[i] << " ";
    }
    cout << endl;
    return 0;
}

运行结果: 文章配图

2.2 范围 for 循环遍历

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    for (auto e : s1) {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

运行结果: 文章配图

2.3 迭代器遍历

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    string::iterator it = s1.begin();
    while (it != s1.end()) {
        cout << *it << " ";
        it++;
    }
    cout << endl;
    return 0;
}

运行结果: 文章配图

二、范围 for 和迭代器

1. 迭代器

解释: 迭代器(iterator)扮演着'中介'的角色,就像一个通用的指针,能够让你以统一的方式访问容器中的元素,而无需关心容器底层到底是怎么实现的。

以上面的例子为例:可以形象理解为遥控器与传送带。

  • *it(解引用):按下按钮,获取当前传送带位置上的物品(字符)。
  • ++it(自增):让传送带指向下一个物品。
  • begin():遥控器指向传送带的第一个位置。
  • end():遥控器指向传送带最后一个物品之后的空白位置。

目前 string 中的 begin() 与 end() 就是迭代器,它们的语法形式为: iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; 这是正向打印,还有两个反向打印的,分别为 rbegin() 和 rend()。

语法形式: reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const;

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    string::reverse_iterator it = s1.rbegin();
    while (it != s1.rend()) {
        cout << *it << " ";
        it++;
    }
    cout << endl;
    return 0;
}

运行结果: 文章配图

2. 范围 for

2.1 auto 关键字

作用: 让编译器通过初始值自动推导变量的类型,极大简化了冗长的代码,但是也降低了代码的可读性,所以要谨慎使用。

特点:

  1. 用 auto 声明指针类型时,用 auto 和 auto* 没有任何区别,但用 auto 声明引用类型时则必须加 &。
  2. 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
  3. auto 不能作为函数的参数,可以做返回值,但是建议谨慎使用。
  4. auto 不能直接用来声明数组。
2.2 范围 for

特点:

  1. 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11 中引入了基于范围的 for 循环。
  2. for 循环后的括号由冒号':'分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
  3. 范围 for 可以作用到数组和容器对象上进行遍历。范围 for 的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

我们可以将其看作是对迭代的范围的复制,所以就无法改变遍历变量的值。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    for (auto e : s1) {
        e = 'm';
        cout << e << " ";
    }
    cout << endl;
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

可以看出 s1 的结果并没有改变,此时我们可以使用 &。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    for (auto &e : s1) {
        e = 'm';
        cout << e << " ";
    }
    cout << endl;
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

三、有关 string 容量的函数

其实 string 的底层是由指针(指向存放字符的内存地址)、大小(Size):记录当前有效字符的数量、容量(Capacity):记录当前分配的总空间大小、内部缓冲区(Local Buffer):用于存放短字符串的固定大小数组这几个内部成员组成。

1. capacity

**容量(Capacity)**就是记录当前分配的总空间大小,这个容量不一定等于 size,它可以相等或更大,额外的空间允许对象在字符串中添加新字符。

容量的大小是会变化的,举一个例子:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    size_t sz = s1.capacity();
    cout << "capacity changed: " << sz << '\n';
    cout << "making s grow:\n";
    for (int i = 0; i < 100; ++i) {
        s1.push_back('c');
        if (sz != s1.capacity()) {
            sz = s1.capacity();
            cout << "capacity changed: " << sz << '\n';
        }
    }
    cout << endl;
    return 0;
}

运行结果: 文章配图

可以看出容量的变化并不是按照 2 倍的扩容变化的,而是以下的规则: 在 VS 中,默认会为对象开辟一个 16 字节的内部缓冲区(其中 1 字节用于存放末尾的 \0),只要字符串长度小于 15,数据就直接存在栈上的对象内部,不涉及堆内存分配,当字符串长度超过 16 后,是先扩大两倍后,再扩 1.5 倍。 然而在 DevC++ 中按照 2 倍扩大的。

1.1 reserve

如果我们想要提前扩容,或者已知需要的空间,就可以用这个函数。

语法形式: void reserve(size_t n = 0);

规则: 如果 n 大于当前字符串容量,函数会使容器的增加到 n 个字符(或更大),在其他所有情况下,将字符串容量的缩小视为非约束,实现可以自由优化其他方式,使字符串容量大于 n。该函数不影响字符串长度,也无法改变其内容。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    s1.reserve(100);
    cout << s1.capacity() << endl;
    cout << endl;
    return 0;
}

运行结果: 文章配图

2. 其它的容量函数

2.1 clear

作用: 擦除字符串的内容,字符串变成空字符串(长度为 0 字符)。

语法形式: void clear();

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    s1.clear();
    cout << s1.size() << endl;
    cout << endl;
    return 0;
}

控制台输出: 文章配图

2.2 empty

作用: 测试字符串是否空。

语法形式: bool empty() const;

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    s1.clear();
    if (s1.empty()) {
        cout << "字符串为空" << endl;
    }
    return 0;
}

运行结果: 文章配图

四、常用的成员函数

1. operator+=

string 支持在字符串末尾相加。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    cout << s1 << endl;
    s1 += " Hello kong";
    cout << s1 << endl;
    return 0;
}

2. push_back

作用: 在字符串末尾附加字符 c。

语法形式: void push_back(char c);

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    cout << s1 << endl;
    s1.push_back(' ');
    s1.push_back('m');
    cout << s1 << endl;
    return 0;
}

3. append

语法形式:

  1. string& append(const string& str); 作用: 添加一串字符串。 示例:
    #include <iostream>
    #include <string>
    using namespace std;
    int main() {
        string s1("HelloWorld");
        cout << s1 << endl;
        s1.append("geerghre");
        cout << s1 << endl;
        return 0;
    }
    
  2. string& append(const string& str, size_t subpos, size_t sublen); 作用: 从字符位置 subpos 开始并跨越 sublen 字符添加一串字符串。 示例:
    #include <iostream>
    #include <string>
    using namespace std;
    int main() {
        string s1 = "I love ";
        string s2 = "C++ Programming";
        // 参数解释:
        // s2: 源字符串
        // 4: 从索引 4 开始(即第 5 个字符 'P')
        // 7: 截取 7 个字符(即 "Program")
        s1.append(s2, 4, 7);
        cout << s1 << endl; // 输出:I love Program
        return 0;
    }
    

4. substr

作用: 生成子串。

语法形式: string substr(size_t pos = 0, size_t len = npos) const;

说明: 返回一个新构建的对象,其值初始化为该对象子字符串的副本,子串是对象中从字符 pos 位置开始并跨越字符 len(或直到字符串末尾,以先到者为准)的部分。

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    string s2;
    s2 = s1.substr(5);
    cout << s2 << endl;
    return 0;
}

运行结果: 文章配图

5. find 与 replace

5.1 find

作用: 搜索字符串中参数指定的序列的首次出现,当指定了 pos 时,搜索只包括位置 pos 及其后字符,忽略任何可能包含 pos 之前字符的情况,如果没有就返回 npos。

语法形式: size_t find(const string& str, size_t pos = 0) const;

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("HelloWorld");
    size_t pos = s1.find('#');
    if (pos == string::npos) {
        cout << "没有这个字符串" << endl;
    }
    return 0;
}
5.2 replace

作用: 用新内容替换字符串中从字符 pos 开始并跨成 len 字符的部分。

语法形式: string& replace(size_t pos, size_t len, const string& str);

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1("Hello.Worl.dtdjd.dhsdjt");
    size_t pos = s1.find('.');
    while (pos != string::npos) {
        s1.replace(pos, 1, "##");
        pos = s1.find('.', pos + 2);
    }
    cout << s1 << endl;
    return 0;
}

运行结果: 文章配图

6. getline

作用: 可用于处理含有空格的字符串。

语法形式: istream& getline(istream& is, string& str);

示例:

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1, s2;
    cout << "请输入 s1 的字符串:";
    cin >> s1;
    cout << "s1 的字符串为:";
    cout << s1 << endl << endl;
    cout << "请输入 s2 的字符串:";
    getline(cin, s2);
    cout << "s2 的字符串为:";
    cout << s2 << endl;
    return 0;
}

运行结果: 文章配图

目录

  1. 一、string 的初始化与遍历
  2. 1. string 的初始化
  3. 1.1 默认初始化(创建一个空字符串 "")
  4. 1.2 直接构造(显式调用构造函数)
  5. 1.3 拷贝构造(利用已有的 string 对象创建一个副本)
  6. 2. string 的遍历
  7. 2.1 下标访问
  8. 2.1.1 size() 函数与 length() 函数
  9. 2.1.2 operator[]
  10. 2.1.3 下标遍历
  11. 2.2 范围 for 循环遍历
  12. 2.3 迭代器遍历
  13. 二、范围 for 和迭代器
  14. 1. 迭代器
  15. 2. 范围 for
  16. 2.1 auto 关键字
  17. 2.2 范围 for
  18. 三、有关 string 容量的函数
  19. 1. capacity
  20. 1.1 reserve
  21. 2. 其它的容量函数
  22. 2.1 clear
  23. 2.2 empty
  24. 四、常用的成员函数
  25. 1. operator+=
  26. 2. push_back
  27. 3. append
  28. 4. substr
  29. 5. find 与 replace
  30. 5.1 find
  31. 5.2 replace
  32. 6. getline
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Agent 开发的三重境界:从 API 调用到自主智能
  • Java 包装类与泛型核心解析
  • AI 时代的内容创作:从代码到认知的范式转移
  • MySQL 详细安装与配置完整教程
  • mdev 与 udev:嵌入式及桌面 Linux 设备管理对比
  • 7 款热门 Claude Skills 开源工具:GitHub 精选技能库
  • Python 遍历目录
  • 手写 C++ TCP 服务器:自定义协议与粘包处理实战
  • Python 纪念币预约自动化工具实现与部署
  • Verilog 实现半加器:FPGA 硬件入门实战
  • 鸿蒙游戏开发:AI 驱动的智能 NPC 实现体验
  • OpenClaw 本地部署飞书机器人配置指南
  • 前端函数防抖详解:原理、手写与 Lodash 实战
  • 使用双指针解决链表问题
  • 元迁移学习:快速适应新任务的方法与原理
  • Dify 集成 MySQL 实战:基于 MCP 协议的数据查询方案
  • 医疗 AI 可信系统全栈实现:向量索引与贝叶斯网络(下)
  • 金仓 KingbaseES 融合架构实践:从多库并存到一库多能
  • C++高性能事件循环库libev封装实战
  • 编写第一个 Rocket 0.5 Web 应用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online