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

C++ 模板与 String 类详解

综述由AI生成C++ 模板机制允许编写与类型无关的通用代码,通过函数模板和类模板实现泛型编程。STL 标准库中的 string 类提供了丰富的接口用于字符串操作,包括构造、迭代器访问、容量管理、元素访问及修改功能。掌握模板实例化原则及 string 常用 API 有助于提升 C++ 开发效率与代码复用性。

日志猎手发布于 2026/3/30更新于 2026/6/818 浏览
C++ 模板与 String 类详解

一、模板

1. 函数模板

什么是模板? 模板是一个模具,只需要往这个模具里倒入不同的材料,就可以获得不同材料的铸件。

如果我们要实现一个交换函数呢?这是很容易的事情。

在这里插入图片描述

但是这种交换函数只能实现整型之间的交换,如果想进行浮点数交换或字符型交换呢?虽然可以通过函数重载实现不同的交换函数,但这样做太浪费时间了,没有意义。毕竟只是改变了交换函数参数的类型,代码不需要变化。所以,这种方法是有缺陷的:

  1. 代码复用率低。
  2. 可维护性差。

所以,有了函数模板,这是实现泛型编程的基础。

所谓泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段。

在这里插入图片描述

template<typename T>就是定义了一个模板,通过一份代码就可以实现多个要求。

这里的typename也可以换成class,这两个的区别会在后面讲解。

这个就叫做函数模板,函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

函数模板的格式:template<typename T1, typename T2, ..., typename Tn>。

2. 函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以,其实模板就是将本来应该我们重复性做的工作交给了编译器。

在这里插入图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。

3. 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。

模板参数实例化分为:隐式实例化和显式实例化。

隐式实例化:让编译器根据实参推演模板参数的实际类型。

在这里插入图片描述

在这里插入图片描述

显式实例化:在函数名后的<>中指定模板参数的实际类型。

在这里插入图片描述

4. 模板参数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以实例化为这个非模板函数。

在这里插入图片描述

  1. 对于非模板函数和同名函数模板,如果其它条件相同,在调用时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生出一个更好匹配的函数,那么将选择模板。

在这里插入图片描述

  1. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。

5. 类模板

类模板的定义格式

template <class T1, class T2, ..., class Tn> class 类模板名 {
    // 类内成员定义
};

在这里插入图片描述

类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

// Stack 是类名,Stack<int>才是类型
Stack<int> st1; // int
Stack<double> st2; // double

二、STL 简介

什么是 STL 呢?

STL 是 C++ 标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。

那么,我们需要学习 STL 的哪些部分呢?

在这里插入图片描述

主要学习五个部分,空间配置器直接使用即可。

三、String

学习 string 从两方面去学习,一个是了解 string 类的接口,另一个便是模拟实现 string。

在这里插入图片描述

string 是被 typedef 的,真名叫做 basic_string<char>,是用来存储字符的。

1. 构造函数

// 无参构造
string();

// 拷贝构造
string(const string& str);

// 字符串构造 (from c-string)
string(const char* s);

// 不太常用的
// 从 pos 位置开始,拷贝 str 字符串的后 len 个字符,如果 str 字符串
// 太短或者 len 为 npos,那就从 pos 位置拷贝到 str 字符串末尾
string(const string& str, size_t pos, size_t len = npos);

// 用 n 个连续的字符 c 的拷贝填充
string(size_t n, char c);

// 赋值
string& operator=(const string& str);

在这里插入图片描述

在这里插入图片描述

2. 迭代器

// 如果 string 对象是一个 const 类型的,函数返回 const_iterator,否则,返回 iterator
// 普通迭代器
iterator begin();          // 指向字符串的开始
iterator end();             // 指向字符串的末尾(最后一个字符的下一个位置)
const_iterator begin() const;
const_iterator end() const;

// 反向迭代器
// 反向迭代器指向 string 的反向开始位置(也就是 string 的末尾最后一个字符)
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

// 指向 string 的末尾的反向(也就是 string 的第一个字符的前一个位置)
reverse_iterator rend();
const_reverse_iterator rend() const;

在这里插入图片描述

注:迭代器可以理解成像指针一样,但是迭代器不是指针。

3. 容量管理

// size 和 length 两个函数的功能是一致的
// 字符串的字节数
size_t size() const;
size_t length() const;

// 字符串的容量
size_t capacity() const;

// 清空字符串
void clear();

// 判断字符串是否为空,length 为 0 返回 true,否则,返回 false
bool empty() const;

// n 代表新的字符串的长度,c 是用来填充字符串中新的字符空间的字符
// 如果 n 小于当前字符串的长度,字符串会缩短至前 n 个字符,删除第
// n 个字符之后的所有字符
// 如果 n 大于当前字符串的长度,在字符串的末尾插入字符到 n 个
// (c 是一个具体的字符,就用 c 来初始化,否则就用空字符初始化)
void resize(size_t n);
void resize(size_t n, char c);

// 请求调整字符串的容量,适应将字符串的长度更改为最多 n 个字符的需求
// 如果 n > str.capacity,容器的容量会增加到 n 个字符(capacity >= n)
// 其它情况,缩小字符串的容量是一个非强制性的请求
// 这个函数不会影响字符串的长度和内容,也就是说即使缩容也不会
// 比字符串的长度小
void reserve(size_t n = 0);

// 减少字符串的容量去适应它的 size
// 不影响字符串的长度和内容
void shrink_to_fit();

shrink_to_fit通常是异地缩容,因为无法从内存块的中间释放一部分内存。

在这里插入图片描述

在这里插入图片描述

这是在 VS 上运行的结果,是没有缩容的,那么,看一下 g++ 编译器会不会进行缩容呢?

在这里插入图片描述

g++ 下也是没有缩容的。是否缩容,取决于平台。

4. 元素访问

// 返回在字符串中 pos 位置的字符的引用
char& operator[](size_t pos);
const char& operator[](size_t pos) const;

// 与 [] 的功能一样,这也是为什么 string 被吐槽的原因,设计了太
// 多的函数,有些函数功能是一样的,重点掌握 [] 的使用
char& at(size_t pos);
const char& at(size_t pos) const;

// 返回的是字符串中最后一个字符的引用
char& back();
const char& back() const;

// 返回的是字符串中第一个字符的引用
char& front();
const char& front() const;

在这里插入图片描述

5. 修改操作

// 在字符串的末尾追加另一个 std::string str 对象
string& operator+=(const string& str);

// 字符串的末尾追加 C 风格的 s 字符串 c-string
string& operator+=(const char* s);

// 在字符串的末尾追加单个字符 character
string& operator+=(char c);

// 追加 str 的拷贝
string& append(const string& str);

// 从 str 的 subpos 位置开始,拿取 sublen 个字符,追加到 string
// 的对象中,如果 str 太短或者 sublen 等于 npos,那就取到 str 的
// 末尾
string& append(const string& str, size_t subpos, size_t sublen);

// s 指向的以空字符结尾的字符序列,追加到 string 对象中 c-string
string& append(const char* s);

// 取 s 指向的字符数组前 n 个字符,追加到 string 对象中 buffer
string& append(const char* s, size_t n);

// n 个字符 c 的拷贝,追加到 string 对象中 fill
string& append(size_t n, char c);

// 在 string 对象的末尾添加字符 c,string 对象的长度增加 1
void push_back(char c);

// 删除 string 对象的最后一个字符,string 对象的长度减 1
void pop_back();

// 在 pos 位置插入 str 的拷贝
string& insert(size_t pos, const string& str);

// 从 str 中的 subpos 位置开始,取 sublen 个字符,插入到 string
// 对象中,如果 str 太短或者 sublen 等于 npos,就从 subpos 位置
// 开始一直到 str 字符串的末尾
string& insert(size_t pos, const string& str, size_t subpos, size_t sublen);

// s 指向的以空字符结尾的字符序列,插入到 string 对象中 c-string
string& insert(size_t pos, const char* s);

// s 指向的字符数组的前 n 个字符的拷贝插入到 string 对象中 buffer
string& insert(size_t pos, const char* s, size_t n);

// 插入字符 c 的 n 次拷贝 fill
string& insert(size_t pos, size_t n, char c);

// 从 pos 位置开始,删除 string 的 len 个字符,如果 string 太短或者 len 为 npos,就删到 string 的末尾。
// 注意,该函数默认删除 string 的所有字符 sequence
string& erase(size_t pos = 0, size_t len = npos);

// 从 string 对象中的 pos 位置,用 str 字符串替换掉 string 对象中的 len 个字符
string& replace(size_t pos, size_t len, const string& str);

// 拷贝 str 字符串赋值给 string 对象
string& assign(const string& str);

在这里插入图片描述

注:insert,erase,replace 需慎用,因为 string 的底层是数组,在插入,删除,数据时,都需要移动数据,这也就意味着时间复杂度为 O(N),而替换数据,如果替换的字符串和 len 是相等的,那还是很高效的,但是如果不相等,也需要移动数据,时间复杂度也为 O(N)。

// 得到一个 C 风格的字符串
const char* c_str() const;

// 从 pos 位置开始查找一个 string 对象
size_t find(const string& str, size_t pos = 0) const;

// 从 pos 位置开始查找一个字符串 c-string
size_t find(const char* s, size_t pos = 0) const;

// 从 pos 位置查找 s 指向的字符数组的前 n 个字符 buffer
size_t find(const char* s, size_t pos, size_t n) const;

// 从 pos 位置查找单个字符 character
size_t find(char c, size_t pos = 0) const;

// 反向查找,与 find 的功能是一样的,只不过一个从 string 的开头处查找,一个从 string 的末尾查找
size_t rfind(const string& str, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos, size_t n) const;
size_t rfind(char c, size_t pos = npos) const;

// 在字符串中查找第一个出现在指定字符集合中的字符
// 成功返回第一个匹配字符的位置,失败返回 npos
size_t find_first_of(const string& str, size_t pos = 0) const;

// 从 pos 位置开始取 len 个字符组成一个子串,构造一个新的 string 对象并返回(或者到字符串的末尾,如果 len 大于从 pos 位置开始剩余字符的长度)
string substr(size_t pos = 0, size_t len = npos) const;

// 从 pos 位置开始,拷贝 string 对象中的 len 个字符,存储在 s 指向的字符数组里
size_t copy(char* s, size_t len, size_t pos = 0) const;

npos是一个 size_t 类型,值为 -1,实际值是一个无穷大的数,因为 size_t 是一个无符号整型。

在这里插入图片描述

在这里插入图片描述

6. 非成员函数

// 获取一行字符
// is 输入流对象,str 存储字符的字符串对象,delim 提取字符的分割符
istream& getline(istream& is, string& str, char delim);
istream& getline(istream& is, string& str);

在这里插入图片描述

目录

  1. 一、模板
  2. 1. 函数模板
  3. 2. 函数模板的原理
  4. 3. 函数模板的实例化
  5. 4. 模板参数的匹配原则
  6. 5. 类模板
  7. 二、STL 简介
  8. 三、String
  9. 1. 构造函数
  10. 2. 迭代器
  11. 3. 容量管理
  12. 4. 元素访问
  13. 5. 修改操作
  14. 6. 非成员函数
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 15 个提示词技巧降低 AIGC 检测率,提升文本自然度
  • Qwen-Image-2512 V2 模型特性与 ComfyUI/WebUI 部署指南
  • 本地运行 Google 开源 AI 大模型 Gemma 完整教程
  • Redis Set 数据结构与 C++ 实战指南
  • 基于 ESP32-C5 的 Moji 2.0 小智 AI 桌面机器人复刻方案
  • P2P 网络(Peer-to-Peer Network)基础架构与区块链应用
  • Rust 异步微服务架构最佳实践与反模式规避
  • C++ STL set/map 模拟实现
  • AI 视频生成模型构建、实现与调试指南
  • Meta-Llama-3-8B-Instruct 部署避坑指南:vLLM 多卡配置详解
  • Java 反射与方法句柄:动态编程深度解析
  • VSCode Cline 配置使用 GPT-5.4 和 Copilot 模型
  • Arduino BLDC 机器人 IMU 角度读取与 PID 互补滤波控制
  • 链表核心算法实战:从基础操作到复杂变换
  • ESP32 开发板创建同步 WebServer 网页服务器
  • 动态规划经典案例:买卖股票问题详解
  • 腾讯云服务器部署 OpenClaw 对接飞书实战
  • CCF 大模型论坛北京会议:大模型技术进展与挑战探讨
  • PromptPilot 工具使用指南:实现 Prompt 精准优化与迭代
  • Python 高效清理 Excel 空白行列:原理与实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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