cpp 10 vector 容器的初始化方式 | static_cast<int>(x) | assign 函数
1 vector 容器的初始化方式
vector<ListNode*> result(k, nullptr);
你问的 vector<ListNode*> result(k, nullptr); 是 C++ 中vector 容器的初始化方式,我会用通俗的语言帮你拆解,让你彻底理解。
核心含义
这句话的作用是:创建一个名为 result 的 vector 容器,容器里装的是 ListNode* 类型(链表节点指针),容器初始长度为 k,且每个位置的初始值都是 nullptr。
逐部分拆解
我们把代码拆成 3 个关键部分来看:
| 代码片段 | 含义 |
|---|---|
vector<ListNode*> |
定义容器的类型:
|
result |
这个 vector 容器的名字,后续可以通过 result[0]、result[1] 等访问里面的元素 |
(k, nullptr) |
初始化参数: ① ② |
举个例子(结合题目场景)
比如题目示例 1 中 k=5,执行这句话后:
result的长度是 5(对应要分割成 5 个部分);result[0]、result[1]、result[2]、result[3]、result[4]初始值都是nullptr;- 后续我们会把分割后的链表头节点依次赋值给
result[0]、result[1]等,没赋值的位置(比如示例 1 的result[3]、result[4])就保留nullptr,正好符合题目「不足 k 个部分时用 null 填充」的要求。
对比其他初始化方式(帮你加深理解)
为了让你更清楚这种初始化的优势,对比几种常见的 vector 初始化:
vector<ListNode*> result;:创建空的 vector,长度为 0,后续需要用push_back逐个添加元素;vector<ListNode*> result(k);:创建长度为k的 vector,每个位置的初始值是「默认值」(指针类型的默认值也是nullptr,和你的写法效果一样);vector<ListNode*> result(k, nullptr);:显式指定初始值为nullptr,代码可读性更高(尤其是新手,一眼就能看出初始值是啥)。
总结
vector<ListNode*> result(k, nullptr);核心是创建长度为 k、每个元素都是空指针的链表节点指针数组;- 这种写法适配题目需求:提前预留 k 个位置,不足的部分用
nullptr填充,符合「分割成 k 个部分,不足则为 null」的要求; - 显式指定
nullptr比只写(k)更易读,是新手推荐的写法。
2 static_cast<int>(x)
cost[i] = abs(static_cast<int>(s[i]) - static_cast<int>(t[i]));
这行代码里,核心涉及到C++ 的强制类型转换(static_cast)、char 与 int 的隐式转换以及 绝对值函数(abs)的使用,我会逐个拆解这些语法点,让你清楚理解。
1. static_cast<int>():静态强制类型转换
这是 C++ 中最常用的强制类型转换方式,属于编译期的静态转换,也是 C++ 推荐的类型转换语法(替代 C 语言的(int)强制转换)。
作用
将一种兼容的类型转换为另一种类型,比如这里把char类型的s[i]和t[i]转换为int类型。
为什么需要这里的转换?
- 在 C++ 中,
char本质上是一个8 位的整数类型(可能是signed char或unsigned char,取决于编译器)。 - 如果直接用
char相减,比如s[i]是'\x7f'(ASCII 127),t[i]是'\x80'(超出 ASCII 的范围),在signed char下,'\x80'会被解析为 - 128,此时相减的结果会出现符号错误。 - 用
static_cast<int>(char)可以将char的值无歧义地转换为对应的整数值(ASCII 码),避免符号问题。
对比 C 语言的强制转换
// C语言风格的强制转换(不推荐,类型安全差)
int diff = (int)s[i] - (int)t[i];
// C++的static_cast(推荐,编译期检查类型兼容性)
int diff = static_cast<int>(s[i]) - static_cast<int>(t[i]);
2. abs ():绝对值函数
abs()是 C++ 标准库中的绝对值函数,定义在<cmath>头文件中(也可以用<cstdlib>),用于计算数值的绝对值。
这里的作用
因为s[i]和t[i]的 ASCII 码差值可能是负数(比如s[i]='b'(98),t[i]='a'(97),差值是 1;反之差值是 - 1),而我们需要的是开销(非负的差值),所以用abs()取绝对值。
3. 赋值语句:cost [i] = ...
cost是你定义的vector<int>类型的数组,cost[i]表示数组中第i个元素,将前面计算的绝对值结果赋值给它,这是 C++ 中最基础的赋值语法。
完整语法拆解示例
我们用一个具体的例子来拆解执行过程:
string s = "a";
string t = "b";
// s[0]是字符'a',对应的ASCII码是97(char类型)
// t[0]是字符'b',对应的ASCII码是98(char类型)
// 步骤1:将char转换为int
int s_int = static_cast<int>(s[0]); // s_int = 97
int t_int = static_cast<int>(t[0]); // t_int = 98
// 步骤2:计算差值
int diff = s_int - t_int; // diff = -1
// 步骤3:取绝对值
int abs_diff = abs(diff); // abs_diff = 1
// 步骤4:赋值给cost数组
vector<int> cost(1);
cost[0] = abs_diff; // cost[0] = 1
补充:哪些情况需要用 static_cast?
除了char转int,static_cast还常用于这些场景:
- 基本数据类型之间的转换(如
int转double,float转int); - 子类指针 / 引用转父类指针 / 引用(向上转型);
- 空指针转换为指定类型的指针(如
void*转int*); - 枚举类型(
enum)转整数类型。
总结
- static_cast<int>(x) 是 C++ 的静态强制类型转换语法,用于将兼容的类型(如 char)转换为 int,比 C 语言的强制转换更安全,是推荐用法。
- abs() 是标准库的绝对值函数,用于获取数值的非负值,需要包含
<cmath>头文件。 - 这行代码的核心目的是安全计算两个字符的 ASCII 码差值的绝对值,并赋值给开销数组的对应位置。
3 assign 函数
一、assign 函数的核心定义
assign 是 C++ 标准库中 std::vector 的成员函数,其核心语义是:清空当前 vector 的所有元素,并用新的元素集合替换它们,同时自动管理内存(释放原有内存、分配新内存)。
它和直接赋值(vector = ...)的核心区别是:assign 支持更灵活的 “元素来源”(比如指定范围、重复值),而赋值运算符只能接收同类型的 vector 或初始化列表。
二、assign 的所有重载形式(C++11 及以上完整版本)
C++ 为 vector::assign 提供了 3 种常用重载,覆盖不同的使用场景,以下是完整语法和说明:
1. 重载 1:填充指定数量的相同值
语法:
void assign(size_type count, const T& value);
参数说明:
count:要填充的元素个数(无符号整数类型size_type,等价于unsigned int);value:要重复填充的元素值(类型需与vector存储的元素类型一致)。
作用:清空原 vector,然后插入 count 个 value 的拷贝,最终 vector 的大小为 count。
示例:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4}; // 初始值 [1,2,3,4]
// 清空原有元素,填充 5 个值为 10 的元素
vec.assign(5, 10);
// 输出:10 10 10 10 10
for (int num : vec) cout << num << " ";
return 0;
}
2. 重载 2:通过迭代器范围赋值(最常用)
语法:
template <class InputIt>
void assign(InputIt first, InputIt last);
参数说明:
first/last:输入迭代器(Input Iterator),表示元素范围[first, last)(左闭右开,包含first指向的元素,不包含last指向的元素)。- 迭代器可以来自任意容器(
vector/list/string等),只要元素类型与当前vector兼容。
作用:清空原 vector,然后将 [first, last) 范围内的所有元素拷贝到当前 vector 中,最终 vector 的大小等于迭代器范围的元素个数。
示例:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5};
vector<int> vec2 = {10, 20, 30};
// 用 vec1 的 [1,4) 范围(元素 2,3,4)替换 vec2 的所有元素
vec2.assign(vec1.begin() + 1, vec1.end() - 1);
// 输出:2 3 4
for (int num : vec2) cout << num << " ";
// 扩展:从 string 迭代器赋值(char 转 int)
string s = "abc";
vector<char> vec3;
vec3.assign(s.begin(), s.end()); // vec3 = {'a','b','c'}
return 0;
}
3. 重载 3:通过初始化列表赋值(C++11 新增)
语法:
void assign(initializer_list<T> ilist);
参数说明:
ilist:初始化列表({}包裹的元素集合),元素类型需与vector一致。
作用:清空原 vector,然后将初始化列表中的元素拷贝到当前 vector 中,等价于 vector = {元素},但语义上更强调 “覆盖替换”。
示例:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> vec = {"apple", "banana"};
// 用初始化列表替换原有元素
vec.assign({"orange", "grape", "pear"});
// 输出:orange grape pear
for (const string& s : vec) cout << s << " ";
return 0;
}
三、assign 的关键特性(新手必知)
1. 内存管理行为
- 执行
assign时,vector 会先销毁原有所有元素,释放占用的内存; - 然后根据新元素的数量分配足够的内存,再拷贝新元素;
- 最终 vector 的
size()等于新元素的数量,capacity()可能大于等于size()(取决于编译器的内存分配策略)。
2. 异常安全
- 如果新元素的拷贝 / 移动操作不会抛出异常,
assign保证强异常安全(操作失败时,vector 恢复到原状态); - 如果拷贝 / 移动可能抛异常,仅保证基本异常安全(操作失败时,vector 处于合法但未指定的状态)。
3. 与赋值运算符 = 的对比
| 特性 | assign 函数 |
赋值运算符 vector = ... |
|---|---|---|
| 支持重复值填充 | ✅(重载 1) | ❌ |
| 支持迭代器范围 | ✅(重载 2) | ❌ |
| 支持初始化列表 | ✅(重载 3) | ✅(C++11 后) |
| 语义 | 显式 “覆盖替换” | 隐式 “赋值” |
示例对比:
vector<int> vec;
vec = {1,2,3}; // 赋值运算符,等价于 vec.assign({1,2,3})
vec.assign(5, 0); // 只能用 assign,赋值运算符做不到
四、常见使用场景
- 批量替换 vector 内容:比如你之前看到的旋转数组代码,用临时数组的内容替换原数组;
- 快速初始化固定数量的重复值:比如创建一个包含 100 个 0 的 vector(
vec.assign(100, 0)); - 从其他容器拷贝部分元素:比如从
list/string中截取一段元素到 vector; - 清空并重新赋值:比先
clear()再push_back()更高效(减少多次内存分配)。
五、注意事项
- 迭代器失效:执行
assign后,原 vector 的所有迭代器、指针、引用都会失效(因为内存被重新分配); - 元素类型兼容:迭代器范围赋值时,源元素类型必须能隐式转换为目标 vector 的元素类型(比如
char可以转int,但int不能直接转string); - 无符号整数注意:
count参数是size_type(无符号),避免传入负数(比如vec.assign(-1, 0)会编译报错或触发未定义行为)。
总结
vector::assign的核心是清空原元素 + 替换为新元素集合,自动管理内存;- 有 3 种重载形式:填充重复值、迭代器范围、初始化列表,覆盖不同赋值场景;
- 相比赋值运算符
=,assign更灵活(支持重复值、迭代器范围),语义更明确(显式替换)。
掌握这 3 种重载形式,就能在不同场景下高效使用 assign 操作 vector 了。
更多推荐




所有评论(0)