vector 容器的初始化方式

 vector<ListNode*> result(k, nullptr); 

你问的 vector<ListNode*> result(k, nullptr); 是 C++ 中vector 容器的初始化方式,我会用通俗的语言帮你拆解,让你彻底理解。

核心含义

这句话的作用是:创建一个名为 result 的 vector 容器,容器里装的是 ListNode* 类型(链表节点指针),容器初始长度为 k,且每个位置的初始值都是 nullptr

逐部分拆解

我们把代码拆成 3 个关键部分来看:

代码片段 含义
vector<ListNode*>

定义容器的类型:

vector 是 C++ 的动态数组容器,<ListNode*> 表示容器里存的是「链表节点的指针」

result 这个 vector 容器的名字,后续可以通过 result[0]result[1] 等访问里面的元素
(k, nullptr)

初始化参数:

① k:指定 vector 的初始大小(即容器一开始就有 k 个位置);

② nullptr:指定这 k 个位置的初始值(每个位置都默认存空指针)

举个例子(结合题目场景)

比如题目示例 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 初始化:

  1. vector<ListNode*> result;:创建空的 vector,长度为 0,后续需要用 push_back 逐个添加元素;
  2. vector<ListNode*> result(k);:创建长度为 k 的 vector,每个位置的初始值是「默认值」(指针类型的默认值也是 nullptr,和你的写法效果一样);
  3. vector<ListNode*> result(k, nullptr);:显式指定初始值为 nullptr,代码可读性更高(尤其是新手,一眼就能看出初始值是啥)。

总结

  1. vector<ListNode*> result(k, nullptr); 核心是创建长度为 k、每个元素都是空指针的链表节点指针数组
  2. 这种写法适配题目需求:提前预留 k 个位置,不足的部分用 nullptr 填充,符合「分割成 k 个部分,不足则为 null」的要求;
  3. 显式指定 nullptr 比只写 (k) 更易读,是新手推荐的写法。

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 charunsigned 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?

除了charintstatic_cast还常用于这些场景:

  1. 基本数据类型之间的转换(如intdoublefloatint);
  2. 子类指针 / 引用转父类指针 / 引用(向上转型);
  3. 空指针转换为指定类型的指针(如void*int*);
  4. 枚举类型(enum)转整数类型。

总结

  1. static_cast<int>(x) 是 C++ 的静态强制类型转换语法,用于将兼容的类型(如 char)转换为 int,比 C 语言的强制转换更安全,是推荐用法。
  2. abs() 是标准库的绝对值函数,用于获取数值的非负值,需要包含<cmath>头文件。
  3. 这行代码的核心目的是安全计算两个字符的 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,然后插入 countvalue 的拷贝,最终 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,赋值运算符做不到

四、常见使用场景

  1. 批量替换 vector 内容:比如你之前看到的旋转数组代码,用临时数组的内容替换原数组;
  2. 快速初始化固定数量的重复值:比如创建一个包含 100 个 0 的 vector(vec.assign(100, 0));
  3. 从其他容器拷贝部分元素:比如从 list/string 中截取一段元素到 vector;
  4. 清空并重新赋值:比先 clear()push_back() 更高效(减少多次内存分配)。

五、注意事项

  1. 迭代器失效:执行 assign 后,原 vector 的所有迭代器、指针、引用都会失效(因为内存被重新分配);
  2. 元素类型兼容:迭代器范围赋值时,源元素类型必须能隐式转换为目标 vector 的元素类型(比如 char 可以转 int,但 int 不能直接转 string);
  3. 无符号整数注意count 参数是 size_type(无符号),避免传入负数(比如 vec.assign(-1, 0) 会编译报错或触发未定义行为)。

总结

  1. vector::assign 的核心是清空原元素 + 替换为新元素集合,自动管理内存;
  2. 有 3 种重载形式:填充重复值、迭代器范围、初始化列表,覆盖不同赋值场景;
  3. 相比赋值运算符 =assign 更灵活(支持重复值、迭代器范围),语义更明确(显式替换)。

掌握这 3 种重载形式,就能在不同场景下高效使用 assign 操作 vector 了。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐