C++ Primer 第3章:字符串、向量和数组
3.1 命名空间的 using 声明
3.1.1 using 声明的使用
cpp
// using_demo.cpp -- using声明
#include <iostream>
#include <string>
// 方式1:using声明(推荐,精确引入)
using std::cin;
using std::cout;
using std::endl;
using std::string;
// 方式2:using编译指令(不推荐在头文件中使用)
// using namespace std;
int main()
{
// 有了using声明,不需要写 std::
string line;
cout << "请输入一行文字:";
getline(cin, line);
cout << "你输入了:" << line << endl;
return 0;
}
⚠️ 注意:
- 头文件中不应该 使用
using编译指令,会污染包含该头文件的所有文件- 每个
using声明只引入一个名字- 函数内的
using声明只在该函数内有效
3.2 标准库类型 string
3.2.1 string 的定义和初始化
cpp
// string_init.cpp -- string的初始化方式
#include <iostream>
#include <string>
int main()
{
using namespace std;
// 各种初始化方式
string s1; // 默认初始化:空字符串
string s2("Hello"); // 直接初始化:C字符串
string s3 = "Hello"; // 拷贝初始化:等价于s2
string s4(s2); // 直接初始化:拷贝s2
string s5 = s2; // 拷贝初始化:等价于s4
string s6(5, 'a'); // 直接初始化:5个'a' → "aaaaa"
string s7(s2, 1, 3); // 从s2第1位开始取3个字符:"ell"
cout << "s1 = \"" << s1 << "\"" << endl;
cout << "s2 = \"" << s2 << "\"" << endl;
cout << "s6 = \"" << s6 << "\"" << endl;
cout << "s7 = \"" << s7 << "\"" << endl;
// 直接初始化 vs 拷贝初始化
// 直接初始化:string s(args)
// 拷贝初始化:string s = val(使用=号)
return 0;
}
3.2.2 string 的操作
cpp
// string_ops.cpp -- string的常用操作
#include <iostream>
#include <string>
int main()
{
using namespace std;
string s = "Hello, World!";
// ===== 基本操作 =====
cout << "内容:" << s << endl;
cout << "长度:" << s.size() << endl; // 13(返回size_type,无符号类型)
cout << "长度:" << s.length() << endl; // 同上
cout << "是否空:" << boolalpha << s.empty() << endl;
// ⚠️ size() 返回 string::size_type(无符号类型)
// 不要与 int 混用,可能导致意外结果
string::size_type len = s.size();
// int n = -1;
// if (n < s.size()) // 危险!n被转为无符号,-1变成很大的数
// ===== 比较操作 =====
string s1 = "apple", s2 = "banana";
cout << "\n比较:" << endl;
cout << "apple < banana : " << (s1 < s2) << endl; // true
cout << "apple == apple : " << (s1 == s1) << endl; // true
// 比较规则:逐字符比较,大小写敏感
// ===== 拼接操作 =====
string hello = "Hello";
string world = "World";
string hw = hello + ", " + world + "!";
cout << "\n拼接:" << hw << endl;
// ⚠️ 字符串字面值不能直接相加
// string s = "Hello" + ", "; // ❌ 错误!两个字面值不能相加
string s3 = "Hello";
string s4 = s3 + ", " + "World"; // ✅ 左边有string对象
// ===== 访问字符 =====
cout << "\n访问字符:" << endl;
cout << "s[0] = " << s[0] << endl; // 'H'(不检查边界)
cout << "s.at(0) = " << s.at(0) << endl; // 'H'(检查边界,越界抛异常)
cout << "front = " << s.front() << endl; // 'H'
cout << "back = " << s.back() << endl; // '!'
// 修改字符
s[0] = 'h';
cout << "修改后:" << s << endl;
return 0;
}
3.2.3 处理 string 中的字符(cctype)
cpp
// string_chars.cpp -- 处理string中的字符
#include <iostream>
#include <string>
#include <cctype> // 字符处理函数
int main()
{
using namespace std;
string s = "Hello, World! 123";
// ===== 范围for循环处理每个字符 =====
cout << "统计各类字符:" << endl;
int letters = 0, digits = 0, spaces = 0, others = 0;
for (auto c : s) // c 是 char 类型的副本
{
if (isalpha(c)) letters++;
else if (isdigit(c)) digits++;
else if (isspace(c)) spaces++;
else others++;
}
cout << "字母:" << letters << " 数字:" << digits
<< " 空格:" << spaces << " 其他:" << others << endl;
// ===== 通过引用修改字符 =====
string str = "Hello World";
for (auto& c : str) // c 是引用,可以修改
c = toupper(c);
cout << "转大写:" << str << endl;
// ===== 使用下标访问 =====
string word = "hello";
// 将第一个字符转为大写
if (!word.empty())
word[0] = toupper(word[0]);
cout << "首字母大写:" << word << endl;
// ===== 常用 cctype 函数 =====
char ch = 'A';
cout << "\ncctype函数示例(字符'" << ch << "'):" << endl;
cout << "isalpha: " << boolalpha << (bool)isalpha(ch) << endl;
cout << "isupper: " << (bool)isupper(ch) << endl;
cout << "islower: " << (bool)islower(ch) << endl;
cout << "isdigit: " << (bool)isdigit(ch) << endl;
cout << "tolower: " << (char)tolower(ch) << endl;
return 0;
}
常用 cctype 函数:
| 函数 | 说明 |
|---|---|
isalpha(c) |
c 是字母时为真 |
isdigit(c) |
c 是数字时为真 |
isalnum(c) |
c 是字母或数字时为真 |
isspace(c) |
c 是空白(空格、制表符、换行等)时为真 |
isupper(c) |
c 是大写字母时为真 |
islower(c) |
c 是小写字母时为真 |
ispunct(c) |
c 是标点符号时为真 |
toupper(c) |
返回 c 的大写形式 |
tolower(c) |
返回 c 的小写形式 |
3.3 标准库类型 vector
3.3.1 vector 的定义和初始化
cpp
// vector_init.cpp -- vector的初始化
#include <iostream>
#include <vector>
#include <string>
int main()
{
using namespace std;
// vector 是模板,需要指定元素类型
vector<int> v1; // 空vector
vector<int> v2(10); // 10个元素,每个值为0
vector<int> v3(10, 1); // 10个元素,每个值为1
vector<int> v4 = {1,2,3,4,5}; // 列表初始化
vector<int> v5{1,2,3,4,5}; // 等价于v4
vector<int> v6(v4); // 拷贝v4
vector<string> vs1{"Hello", "World", "C++"};
vector<string> vs2(3, "hi"); // 3个"hi"
// 圆括号 vs 花括号的区别
vector<int> v7(3); // 3个元素,值为0
vector<int> v8{3}; // 1个元素,值为3
vector<int> v9(3, 1); // 3个元素,值为1
vector<int> v10{3, 1}; // 2个元素:3和1
cout << "v7.size() = " << v7.size() << endl; // 3
cout << "v8.size() = " << v8.size() << endl; // 1
cout << "v9.size() = " << v9.size() << endl; // 3
cout << "v10.size() = " << v10.size() << endl; // 2
// 打印 v4
cout << "v4: ";
for (auto x : v4) cout << x << " ";
cout << endl;
return 0;
}
3.3.2 vector 的操作
cpp
// vector_ops.cpp -- vector的常用操作
#include <iostream>
#include <vector>
#include <string>
int main()
{
using namespace std;
vector<int> v;
// ===== 添加元素 =====
// push_back:在末尾添加元素(最常用)
for (int i = 0; i < 10; i++)
v.push_back(i * i); // 0,1,4,9,16,25,36,49,64,81
// ===== 基本属性 =====
cout << "大小:" << v.size() << endl; // 10
cout << "是否空:" << boolalpha << v.empty() << endl;
// ===== 访问元素 =====
cout << "v[0] = " << v[0] << endl; // 0(不检查边界)
cout << "v.at(0) = " << v.at(0) << endl; // 0(检查边界)
cout << "front = " << v.front() << endl; // 0
cout << "back = " << v.back() << endl; // 81
// ===== 遍历 =====
cout << "\n遍历方式:" << endl;
// 方式1:范围for(推荐,只读)
cout << "范围for:";
for (const auto& x : v) cout << x << " ";
cout << endl;
// 方式2:下标
cout << "下标:";
for (size_t i = 0; i < v.size(); i++) cout << v[i] << " ";
cout << endl;
// 方式3:迭代器
cout << "迭代器:";
for (auto it = v.begin(); it != v.end(); ++it) cout << *it << " ";
cout << endl;
// ===== 修改元素 =====
for (auto& x : v) x *= 2; // 每个元素乘2
cout << "\n乘2后:";
for (auto x : v) cout << x << " ";
cout << endl;
// ===== 其他操作 =====
v.pop_back(); // 删除最后一个元素
cout << "pop_back后大小:" << v.size() << endl;
// ⚠️ 不能在范围for循环中向vector添加元素!
// 会使迭代器失效
// ===== vector 的比较 =====
vector<int> a = {1, 2, 3};
vector<int> b = {1, 2, 4};
cout << "\na < b : " << (a < b) << endl; // true(逐元素比较)
return 0;
}
3.3.3 vector 的增长机制
cpp
// vector_growth.cpp -- vector的增长机制
#include <iostream>
#include <vector>
int main()
{
using namespace std;
vector<int> v;
cout << "初始容量:" << v.capacity() << endl;
for (int i = 0; i < 20; i++)
{
v.push_back(i);
cout << "size=" << v.size()
<< " capacity=" << v.capacity() << endl;
}
// reserve:预分配容量(避免频繁扩容)
vector<int> v2;
v2.reserve(100);
cout << "\nreserve(100)后容量:" << v2.capacity() << endl;
// resize:改变大小
v2.resize(10, 0); // 大小变为10,新元素初始化为0
cout << "resize(10)后大小:" << v2.size() << endl;
return 0;
}
💡 vector 的增长策略:
- 当容量不足时,vector 通常将容量翻倍
size():当前元素数量capacity():当前分配的内存能容纳的元素数量reserve(n):预分配至少 n 个元素的空间(不改变 size)resize(n):改变 size,可能改变 capacity
3.4 迭代器
3.4.1 迭代器的基本使用
cpp
// iterator_demo.cpp -- 迭代器基础
#include <iostream>
#include <string>
#include <vector>
int main()
{
using namespace std;
string s = "Hello, World!";
vector<int> v = {1, 2, 3, 4, 5};
// ===== 获取迭代器 =====
// begin():指向第一个元素
// end():指向最后一个元素的下一位置(尾后迭代器)
auto b = s.begin(); // string::iterator
auto e = s.end(); // string::iterator
// ===== 解引用和递增 =====
cout << "第一个字符:" << *b << endl; // 'H'
++b;
cout << "第二个字符:" << *b << endl; // 'e'
// ===== 遍历 =====
cout << "遍历string:";
for (auto it = s.begin(); it != s.end(); ++it)
cout << *it;
cout << endl;
// ===== 修改元素(非const迭代器)=====
for (auto it = s.begin(); it != s.end(); ++it)
*it = toupper(*it);
cout << "转大写:" << s << endl;
// ===== const 迭代器(只读)=====
// cbegin() 和 cend() 返回 const_iterator
for (auto it = v.cbegin(); it != v.cend(); ++it)
cout << *it << " ";
cout << endl;
// ===== 迭代器运算(随机访问迭代器)=====
auto mid = v.begin() + v.size() / 2;
cout << "中间元素:" << *mid << endl;
// 迭代器相减得到距离
auto dist = v.end() - v.begin();
cout << "距离:" << dist << endl; // 5
return 0;
}
3.4.2 迭代器类型与操作
cpp
// iterator_types.cpp -- 迭代器类型
#include <iostream>
#include <vector>
#include <string>
int main()
{
using namespace std;
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// iterator:可读可写
vector<int>::iterator it1 = v.begin();
// const_iterator:只读
vector<int>::const_iterator it2 = v.cbegin();
// auto 简化类型名
auto it3 = v.begin(); // vector<int>::iterator
auto it4 = v.cbegin(); // vector<int>::const_iterator
// ===== 迭代器运算(string和vector支持)=====
// it + n:向后移动n步
// it - n:向前移动n步
// it1 - it2:两个迭代器之间的距离
// it1 < it2:比较位置
// 二分查找示例
auto beg = v.begin(), end = v.end();
auto mid = beg + (end - beg) / 2;
int target = 7;
while (mid != end && *mid != target)
{
if (target < *mid)
end = mid;
else
beg = mid + 1;
mid = beg + (end - beg) / 2;
}
if (mid != v.end() && *mid == target)
cout << "找到 " << target << ",位置:"
<< (mid - v.begin()) << endl;
// ===== 反向迭代器 =====
cout << "反向遍历:";
for (auto it = v.rbegin(); it != v.rend(); ++it)
cout << *it << " ";
cout << endl;
return 0;
}
迭代器操作总结:
| 操作 | 说明 |
|---|---|
*it |
解引用,返回迭代器所指元素的引用 |
it->mem |
等价于 (*it).mem |
++it |
令 it 指向下一个元素 |
--it |
令 it 指向上一个元素 |
it1 == it2 |
判断两个迭代器是否相等 |
it + n |
向后移动 n 步(随机访问迭代器) |
it - n |
向前移动 n 步(随机访问迭代器) |
it1 - it2 |
两迭代器间的距离(随机访问迭代器) |
3.5 数组
3.5.1 数组的定义和初始化
cpp
// array_init.cpp -- 数组的定义和初始化
#include <iostream>
int main()
{
using namespace std;
// 数组大小必须是常量表达式
constexpr int sz = 5;
// 各种初始化方式
int a1[10]; // 未初始化(局部数组,值未定义)
int a2[sz] = {0,1,2,3,4}; // 列表初始化
int a3[] = {0,1,2,3,4}; // 省略大小,自动推断为5
int a4[5] = {0,1,2}; // 部分初始化:{0,1,2,0,0}
int a5[5] = {}; // 全部初始化为0
string sa[3] = {"hi", "bye", "now"};
// 字符数组的特殊性
char c1[] = {'C', '+', '+'}; // 大小为3,没有空字符
char c2[] = {'C', '+', '+', '\0'}; // 大小为4,有空字符
char c3[] = "C++"; // 大小为4,自动添加'\0'
// const char c4[3] = "C++"; // ❌ 错误:空间不够
cout << "a2: ";
for (int x : a2) cout << x << " ";
cout << endl;
cout << "a4: ";
for (int x : a4) cout << x << " ";
cout << endl;
cout << "c3: " << c3 << endl;
// ⚠️ 数组不能拷贝和赋值
// int a6[] = a2; // ❌ 错误:不能用数组初始化另一个数组
// a1 = a2; // ❌ 错误:不能把数组赋值给另一个数组
return 0;
}
3.5.2 数组的访问与遍历
cpp
// array_access.cpp -- 数组的访问
#include <iostream>
#include <string>
int main()
{
using namespace std;
int scores[5] = {85, 92, 78, 96, 88};
// ===== 下标访问 =====
cout << "scores[0] = " << scores[0] << endl;
cout << "scores[4] = " << scores[4] << endl;
// ===== 范围for遍历 =====
cout << "范围for:";
for (const auto& s : scores)
cout << s << " ";
cout << endl;
// ===== 指针遍历 =====
// 数组名是指向第一个元素的指针
int* p = scores; // 等价于 int* p = &scores[0]
cout << "指针遍历:";
for (int i = 0; i < 5; i++)
cout << *(p + i) << " ";
cout << endl;
// ===== begin() 和 end()(C++11)=====
// 使用标准库函数获取数组的首尾指针
int* beg = begin(scores);
int* end = end(scores);
cout << "begin/end遍历:";
for (int* it = beg; it != end; ++it)
cout << *it << " ";
cout << endl;
// ===== 计算数组大小 =====
int sz = end(scores) - begin(scores); // 5
// 或者:
int sz2 = sizeof(scores) / sizeof(scores[0]); // 5
cout << "数组大小:" << sz << endl;
return 0;
}
3.5.3 指针与数组
cpp
// pointer_array.cpp -- 指针与数组的关系
#include <iostream>
int main()
{
using namespace std;
int ia[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// 数组名就是指向第一个元素的指针
int* p = ia; // 等价于 int* p = &ia[0]
// 指针算术
cout << "*p = " << *p << endl; // 0
cout << "*(p+1) = " << *(p+1) << endl; // 1
cout << "p[2] = " << p[2] << endl; // 2(下标运算)
// 指针递增
++p;
cout << "*p(递增后)= " << *p << endl; // 1
// 指针相减(得到距离)
int* p2 = ia + 5;
ptrdiff_t diff = p2 - ia; // ptrdiff_t:有符号类型,表示指针差值
cout << "p2 - ia = " << diff << endl; // 5
// 指针比较
cout << "ia < p2 : " << boolalpha << (ia < p2) << endl; // true
// 下标可以是负数(对指针有效,对数组名无效)
int* mid = ia + 5;
cout << "mid[-1] = " << mid[-1] << endl; // 4(ia[4])
cout << "mid[0] = " << mid[0] << endl; // 5(ia[5])
// ===== C风格字符串 =====
const char* cp = "Hello";
while (*cp) // 利用'\0'结尾
{
cout << *cp;
++cp;
}
cout << endl;
return 0;
}
3.5.4 多维数组
cpp
// multidim_array.cpp -- 多维数组
#include <iostream>
int main()
{
using namespace std;
// 定义二维数组(3行4列)
int ia[3][4] = {
{0, 1, 2, 3}, // 第0行
{4, 5, 6, 7}, // 第1行
{8, 9, 10, 11} // 第2行
};
// 等价的初始化(不分行)
int ib[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
// 部分初始化
int ic[3][4] = {{0}, {4}, {8}}; // 每行只初始化第一个元素
// ===== 访问元素 =====
cout << "ia[1][2] = " << ia[1][2] << endl; // 6
// ===== 遍历(范围for)=====
cout << "范围for遍历:" << endl;
for (const auto& row : ia) // row 是 int(&)[4],必须用引用!
{
for (const auto& col : row)
cout << col << "\t";
cout << endl;
}
// ===== 遍历(下标)=====
cout << "\n下标遍历:" << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
cout << ia[i][j] << "\t";
cout << endl;
}
// ===== 遍历(指针)=====
cout << "\n指针遍历:" << endl;
for (int (*row)[4] = begin(ia); row != end(ia); ++row)
{
for (int* col = begin(*row); col != end(*row); ++col)
cout << *col << "\t";
cout << endl;
}
// 使用 auto 简化指针类型
cout << "\nauto指针遍历:" << endl;
for (auto p = begin(ia); p != end(ia); ++p)
{
for (auto q = begin(*p); q != end(*p); ++q)
cout << *q << "\t";
cout << endl;
}
// ===== 类型别名简化 =====
using int_array = int[4]; // int_array 是 int[4] 的别名
for (int_array& row : ia)
{
for (int col : row)
cout << col << " ";
cout << endl;
}
return 0;
}
⚠️ 多维数组范围for的注意事项:
- 除最内层循环外,其他循环的控制变量必须是引用类型
- 否则数组会退化为指针,无法继续用范围for遍历
3.6 数组与 vector 的对比
cpp
// array_vs_vector.cpp -- 数组与vector对比
#include <iostream>
#include <vector>
#include <string>
#include <cstring> // C字符串函数
int main()
{
using namespace std;
// ===== C风格字符串 vs string =====
// C风格字符串(字符数组)
char ca[] = "Hello";
char cb[] = "World";
// C字符串操作需要函数
cout << "strlen: " << strlen(ca) << endl;
// strcat(ca, cb); // 危险!可能越界
char cc[20];
strcpy(cc, ca);
strcat(cc, " ");
strcat(cc, cb);
cout << "C字符串拼接:" << cc << endl;
// string(推荐)
string sa = "Hello";
string sb = "World";
string sc = sa + " " + sb; // 简单安全
cout << "string拼接:" << sc << endl;
// ===== 数组 vs vector =====
// 数组:固定大小,不能动态增长
int arr[5] = {1, 2, 3, 4, 5};
// vector:动态大小,功能丰富
vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6); // 动态增长
// ===== 用数组初始化vector =====
int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(begin(int_arr), end(int_arr));
cout << "从数组初始化vector:";
for (auto x : ivec) cout << x << " ";
cout << endl;
// 只取数组的一部分
vector<int> subvec(int_arr + 1, int_arr + 4); // {1,2,3}
cout << "子数组:";
for (auto x : subvec) cout << x << " ";
cout << endl;
return 0;
}
数组 vs vector 对比:
| 特性 | 数组 | vector |
|---|---|---|
| 大小 | 固定(编译时确定) | 动态(运行时可变) |
| 初始化 | 可以列表初始化 | 可以列表初始化 |
| 拷贝/赋值 | ❌ 不支持 | ✅ 支持 |
| 大小查询 | sizeof/end-begin |
.size() |
| 边界检查 | ❌ 无([]) |
✅ .at() 有 |
| 内存管理 | 自动(栈)或手动(堆) | 自动 |
| 推荐程度 | 特殊场景 | 通常推荐 |
3.7 综合示例:文本统计分析
cpp
// text_analysis.cpp -- 综合示例:文本统计分析
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
#include <map>
int main()
{
using namespace std;
// 模拟输入文本
vector<string> lines = {
"Hello World this is a test",
"C++ programming is fun and powerful",
"Vectors and strings are very useful",
"Practice makes perfect in coding"
};
// ===== 统计信息 =====
int totalChars = 0;
int totalWords = 0;
int totalLetters = 0;
int totalDigits = 0;
int totalSpaces = 0;
vector<string> allWords; // 收集所有单词
for (const auto& line : lines)
{
totalChars += line.size();
// 统计字符类型
for (char c : line)
{
if (isalpha(c)) totalLetters++;
else if (isdigit(c)) totalDigits++;
else if (isspace(c)) totalSpaces++;
}
// 提取单词
string word;
for (char c : line)
{
if (isalpha(c))
word += tolower(c); // 转小写
else if (!word.empty())
{
allWords.push_back(word);
totalWords++;
word.clear();
}
}
if (!word.empty())
{
allWords.push_back(word);
totalWords++;
}
}
// ===== 统计词频 =====
map<string, int> wordFreq;
for (const auto& w : allWords)
wordFreq[w]++;
// ===== 输出结果 =====
cout << "===== 文本统计 =====" << endl;
cout << "总行数:" << lines.size() << endl;
cout << "总字符:" << totalChars << endl;
cout << "总单词:" << totalWords << endl;
cout << "字母数:" << totalLetters << endl;
cout << "数字数:" << totalDigits << endl;
cout << "空格数:" << totalSpaces << endl;
cout << "\n===== 词频统计(出现2次以上)=====" << endl;
for (const auto& [word, count] : wordFreq)
if (count >= 2)
cout << word << ": " << count << " 次" << endl;
// ===== 最长单词 =====
auto longest = max_element(allWords.begin(), allWords.end(),
[](const string& a, const string& b) {
return a.size() < b.size();
});
if (longest != allWords.end())
cout << "\n最长单词:" << *longest
<< "(" << longest->size() << " 个字母)" << endl;
// ===== 按字母顺序排序并去重 =====
sort(allWords.begin(), allWords.end());
allWords.erase(unique(allWords.begin(), allWords.end()),
allWords.end());
cout << "\n所有不重复单词(字母序):" << endl;
for (size_t i = 0; i < allWords.size(); i++)
{
cout << allWords[i];
if (i < allWords.size() - 1) cout << ", ";
}
cout << endl;
return 0;
}
📝 第3章知识点总结
| 知识点 | 核心要点 |
|---|---|
| using 声明 | using std::cin 精确引入,头文件中不用 using namespace |
| string 初始化 | 直接初始化(括号)vs 拷贝初始化(等号),string(n, c) 重复字符 |
| string::size_type | size() 返回无符号类型,不要与 int 混用 |
| string 拼接 | + 两侧至少一个 string 对象,字面值不能直接相加 |
| 范围for修改 | 修改元素时循环变量必须是引用 auto& |
| vector 初始化 | (n) 创建n个元素,{n} 创建含n的列表,注意区别 |
| push_back | 运行时动态添加元素,不要在范围for中添加元素 |
| 迭代器 | begin()/end(),cbegin()/cend()(只读),!= 判断结束 |
| 迭代器失效 | 向 vector 添加元素后,所有迭代器可能失效 |
| 数组大小 | 必须是常量表达式,不能拷贝赋值,可用 begin()/end() |
| 数组退化 | 数组名在大多数表达式中退化为指向首元素的指针 |
| 多维数组范围for | 除最内层外,控制变量必须是引用,否则退化为指针 |
| C字符串 | 以 \0 结尾,操作需要 <cstring> 函数,推荐用 string 替代 |
| 数组→vector | vector<int> v(begin(arr), end(arr)) 用数组初始化 vector |