STL(standard template libaray-标准模板库):是c++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包含数据结构与算法的软件框架

在这里补充2个C++11的小语法,方便我们后面的学习。
#include<iostream>
using namespace std;
int func1()
{
return 10;
}
// 不能做参数
void func2(auto a)
{}
// 可以做返回值,但是建议谨慎使用
auto func3()
{
return 3;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = func1();
// 编译报错:rror C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项
auto e;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
int x = 10;
auto y = &x;
auto* z = &x;
auto& m = x;
cout << typeid(x).name() << endl;
cout << typeid(y).name() << endl;
cout << typeid(z).name() << endl;
auto aa = 1, bb = 2;
// 编译报错:error C3538: 在声明符列表中,“auto”必须始终推导为同一类型
auto cc = 3, dd = 4.0;
// 编译报错:error C3318: “auto []”: 数组不能具有其中包含“auto”的元素类型
auto array[] = { 4, 5, 6 };
return 0;
}#include<iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
std::map<std::string, std::string> dict =
{ { "apple", "苹果" },{ "orange","橙子" }, {"pear","梨"} };
// auto的用武之地
//std::map<std::string, std::string>::iterator it = dict.begin();
auto it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
return 0;
}这段代码通过 std::map 存储了三个水果名称及其对应的中文翻译,使用迭代器遍历并打印出每一个键值对。 auto 使得迭代器的类型自动推导,简化了代码。
#
include<iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
// C++98的遍历
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{
array[i] *= 2;
}
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{
cout << array[i] << endl;
}
// C++11的遍历
for (auto& e : array)
e *= 2;
for (auto e : array)
cout << e << " " << endl;
string str("hello world");
for (auto ch : str)
{
cout << ch << " ";
}
cout << endl;
return 0;
}#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1; // 调用默认构造函数,构造一个空字符串
cout << "s1: " << s1 << endl; // 输出空内容
cout << "s1.size(): " << s1.size() << endl; // 输出 0
return 0;
}功能说明: 构造一个空的 string 对象,不包含任何字符。
注意事项: 默认初始化后,size() 返回 0,但可以通过 push_back 或 += 动态添加字符。
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char* cstr = "Hello, C++";
string s2(cstr); // 用C风格字符串构造string对象
cout << "s2: " << s2 << endl; // 输出 "Hello, C++"
return 0;
}功能说明: 通过C风格字符串(const char*)初始化 string 对象。
注意事项: 需确保传入的指针指向有效的以 \0 结尾的字符串,否则行为未定义。
#include <iostream>
#include <string>
using namespace std;
int main() {
string original = "Copy this";
string copy(original); // 调用拷贝构造函数
cout << "copy: " << copy << endl; // 输出 "Copy this"
return 0;
}功能说明: 通过另一个 string 对象构造新对象,内容与原对象完全一致。
注意事项: 深拷贝实现,修改原对象不会影响新对象。
总结:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello";
cout << "s.size(): " << s.size() << endl; // 输出 5
return 0;
}功能说明: 返回字符串中当前存储的有效字符数量(不包含结尾的 \0)。
注意事项: 与 length() 功能完全相同,但 size() 是STL容器的通用接口,推荐优先使用。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "abc";
string s2;
cout << "s1.empty(): " << s1.empty() << endl; // 输出 0(false)
cout << "s2.empty(): " << s2.empty() << endl; // 输出 1(true)
return 0;
}功能说明: 若字符串长度为0(即 size() == 0),返回 true,否则返回 false。
注意事项: 比手动检查 size() == 0 更直观,推荐使用。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello";
s.clear();
cout << "After clear, s: " << s << endl; // 输出空
cout << "s.size(): " << s.size() << endl; // 输出 0
cout << "s.capacity(): " << s.capacity() << endl; // 容量可能不变
return 0;
}功能说明: 清空字符串内容,但不释放内存(capacity() 可能保持不变)。
注意事项: 若需彻底释放内存,可结合 shrink_to_fit()(C++11)使用。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
s.reserve(100); // 预分配至少100字节的空间
cout << "s.capacity(): " << s.capacity() << endl; // 可能 >=100
cout << "s.size(): " << s.size() << endl; // 输出 0(内容仍为空)
return 0;
}功能说明: 提前分配内存以减少后续动态扩容的开销。
注意事项: 实际容量可能大于请求值(由实现决定)。 仅影响容量,不改变内容或长度。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello";
s.resize(8, 'x'); // 扩展至8字符,不足部分用'x'填充
cout << "s: " << s << endl; // 输出 "Helloxxx"
s.resize(3); // 截断至3字符
cout << "s: " << s << endl; // 输出 "Hel"
return 0;
}功能说明: 调整字符串长度: 若 n > size(),填充指定字符(默认 \0)。 若 n < size(),截断多余字符。
注意事项:
总结:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello";
// 非const对象:可读可写
s[0] = 'h'; // 修改第一个字符
cout << s[0] << endl; // 输出 'h'(读取第一个字符)
// const对象:只读
const string cs = "World";
cout << cs[2] << endl; // 输出 'r'(只能读取)
// cs[0] = 'w'; // 错误!const对象不可修改
return 0;
}功能说明: 通过下标直接访问指定位置的字符(从 0 开始)。
注意事项: 不检查越界(若 pos >= size(),行为未定义)。 对 const string 返回 const char&,禁止修改。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "C++";
// 使用迭代器遍历
for (auto it = s.begin(); it != s.end(); ++it)
{
cout << *it << " "; // 输出:C + +
}
cout << endl;
// 修改内容
*s.begin() = 'c'; // 将首字符改为 'c'
cout << s << endl; // 输出 "c++"
return 0;
}功能说明: begin() 返回指向首字符的迭代器,end() 返回末尾的“哨兵”迭代器(指向最后一个字符的下一个位置)。
注意事项: 若字符串为空,begin() == end()。 支持通过迭代器修改字符(除非是 const 迭代器)。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "12345";
// 反向遍历
for (auto rit = s.rbegin(); rit != s.rend(); ++rit)
{
cout << *rit << " "; // 输出:5 4 3 2 1
}
cout << endl;
return 0;
}功能说明: rbegin() 返回指向最后一个字符的反向迭代器,rend() 返回首字符前一个位置的迭代器。
注意事项: 反向迭代器的 ++ 操作会向字符串开头移动。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Range";
// 简洁遍历(只读)
for (char ch : s)
{
cout << ch << " "; // 输出:R a n g e
}
cout << endl;
// 修改内容需用引用
for (char& ch : s)
{
ch = toupper(ch); // 转为大写
}
cout << s << endl; // 输出 "RANGE"
return 0;
}功能说明: 语法上,底层通过 begin() 和 end() 实现。
注意事项: 若需修改元素,需使用 char& 引用类型。
总结:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello";
s += " World"; // 追加字符串
s += '!'; // 追加字符
cout << s << endl; // 输出 "Hello World!"
return 0;
}功能说明: 支持追加另一个 string、C风格字符串或单个字符。
注意事项: 直接修改原字符串,是最常用的拼接方式(高效且简洁)。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string s = "C++";
const char* p = s.c_str(); // 获取C风格字符串指针
cout << "C-string: " << p << endl; // 输出 "C++"
cout << "Length via strlen: " << strlen(p) << endl; // 输出 3
// 注意:若s被修改,p可能失效
s += "11";
// cout << p; // 危险!p可能指向无效内存
return 0;
}功能说明: 返回 const char* 指针,指向以 \0 结尾的字符数组。
注意事项: 不要存储返回的指针,若原 string 被修改,指针可能失效(如扩容后)。 常用于需要C风格字符串的接口(如文件操作、C库函数)。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Hello, C++!";
size_t pos;
// 查找字符
pos = s.find('C');
if (pos != string::npos)
{
cout << "'C' found at: " << pos << endl; // 输出 7
}
// 查找子串
pos = s.find("C++");
if (pos != string::npos)
{
cout << "\"C++\" found at: " << pos << endl; // 输出 7
}
// 查找不存在的字符
pos = s.find('x');
if (pos == string::npos)
{
cout << "'x' not found!" << endl; // 输出此提示
}
return 0;
}功能说明: find() 返回首次匹配的位置(从 0 开始),失败时返回 string::npos。 可查找字符或子串,支持指定起始位置(如 s.find(‘o’, 5))。
注意事项: 检查返回值时必须使用 npos,不可直接与 -1 比较(npos 是无符号类型)。 rfind() 为反向查找(从后往前)。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Programming";
string sub = s.substr(3, 4); // 从位置3开始,截取4个字符
cout << sub << endl; // 输出 "gram"
// 省略长度参数:截取到末尾
sub = s.substr(7);
cout << sub << endl; // 输出 "ming"
return 0;
}功能说明: 返回从 pos 开始、长度为 n 的子串(默认 n 到末尾)。
注意事项: 1. 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。 2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好
总结:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
// 输入示例(遇到空格/换行停止)
cout << "Enter a word: ";
cin >> s; // 输入 "Hello World"
cout << "You entered: " << s << endl; // 输出 "Hello"(空格截断)
// 输出示例
string name = "Alice";
cout << "Name: " << name << endl; // 输出 "Name: Alice"
return 0;
}功能说明: 从流中读取数据到 string,默认以空格/换行分隔。 将 string 输出到流。
注意事项: 会忽略前导空白符,读取到下一个空白符为止。 需配合 getline() 读取整行(见下文)。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line;
cout << "Enter a line: ";
getline(cin, line); // 读取整行(包括空格)
cout << "Line: " << line << endl; // 输出完整输入
// 指定分隔符(默认'\n')
getline(cin, line, ';'); // 读取直到遇到分号
cout << "Until ';': " << line << endl;
return 0;
}功能说明: 从输入流中读取一行(默认以 \n 结尾),可指定分隔符。
注意事项: 与 cin >> 混用时,需先清除缓冲区残留的换行符: cin.ignore(); // 忽略前一个输入的换行
#include <iostream>
#include <string>
using namespace std;
int main()
{
string a = "apple";
string b = "banana";
// 比较示例(按字典序)
cout << boolalpha;
cout << "a < b: " << (a < b) << endl; // 输出 true('a' < 'b')
cout << "a == \"apple\": " << (a == "apple") << endl; // 输出 true
// 支持所有比较运算符:>, >=, <=, !=
return 0;
}功能说明: 按字符的字典序(ASCII值)逐位比较。
注意事项: 比较时区分大小写(“A” < “a” 为真)。 可直接与C风格字符串比较(如 s == “text”)。
string s1 = "Hello", s2 = "World";
string s3 = s1 + " " + s2; // 拼接,但每次+生成临时对象为什么不推荐? 每次 + 操作会生成临时对象,频繁拼接时效率低(尤其是循环中)。 替代方案: 使用 += 或 append() 直接修改原字符串:
string s;
s += s1;
s += " ";
s += s2; // 无额外拷贝总结:

注意:下述结构是在32位平台下进行验证,32位平台下指针占4个字节。
string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义。
string中字符串的存储空间:
这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。 其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量。 最后:还有一个指针做一些其他事情。故总共占16+4+4+4=28个字节。

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指针将来指向一块堆空间,内部包含了如下字段: