赞
踩
目录
6.使用 std::generate 或 std::generate_n
std::fill
是C++标准库中的一个函数,定义在 <algorithm>
头文件中。
std::fill
作用:它用于将指定的值赋给一个给定范围内的所有元素,常用于数据结构初始化
下面是对 std::fill
的代码实例:
- #include <algorithm> // 包含 std::fill
- #include <vector>
-
- int main() {
- std::vector<int> vec = {1, 2, 3, 4, 5};
- std::fill(vec.begin(), vec.end(), 0); // 将 vec 中的所有元素设置为 0
- return 0;
- }
std::fill
有几种不同的重载形式,但最常用的是:
-
- template<class ForwardIterator, class T> void fill(ForwardIterator first, ForwardIterator last, const T& value);
ForwardIterator
: 一个前向迭代器,可以是指向容器元素的迭代器,如 std::vector
、std::list
等。T
: 赋值的类型,可以是任意可赋值类型。first
: 范围的起始迭代器。last
: 范围的结束迭代器(不包括在内)。value
: 要赋给范围内每个元素的值。- #include <algorithm> // 包含 std::fill
- #include <vector>
-
- int main() {
- std::vector<int> vec = {1, 2, 3, 4, 5};
- std::fill(vec.begin(), vec.end(), 10); // 将 vec 中的所有元素设置为 10
-
- int arr[] = {1, 2, 3, 4, 5};
- std::fill(std::begin(arr), std::end(arr), 20); // 使用 std::begin 和 std::end 来获取数组的迭代器
-
- std::list<int> lst = {1, 2, 3, 4, 5};
- std::fill(lst.begin(), lst.end(), 30); // 将 list 中的所有元素设置为 30
-
- return 0;
- }
std::fill
会改变 first
和 last
之间的所有元素,包括 first
但不包括 last
。first
和 last
是相同的迭代器,或者 last
在 first
之前,那么 std::fill
不会执行任何操作。std::fill
可以用于任何类型的迭代器,只要它们支持解引用和赋值操作。std::fill
时,需要确保 value
的类型与容器元素的类型兼容。std::fill
通常用于快速初始化或重置容器中的元素。它的性能取决于赋值操作的复杂性,但对于简单的数据类型,如整数或指针,性能通常非常高效。
对于某些容器,如 std::vector
或 std::array
等,它们提供了自己的 fill
方法,用于将所有元素初始化为一个特定的值。你可以使用它们的构造函数或成员函数 fill
来初始化容器。例如:
- std::vector<int> vec(10, 1); // 创建一个大小为 10 的 vector,所有元素初始化为 1
- std::array<int, 5> arr = {0, 1, 2, 3, 4};
- arr.fill(2); // 将 arr 中的所有元素设置为 2
这些替代方法通常在初始化容器时使用,而 std::fill
更适用于在容器已经存在时修改其内容。
在C++中,除了使用 std::fill
来初始化容器,还可以使用以下几种方法:
对于大多数标准库容器,如 std::vector
、std::array
、std::deque
等,你可以在创建容器时使用构造函数来初始化元素。
std::vector<int> vec(10, 100); // 创建一个包含10个元素的vector,每个元素初始化为100 std::array<int, 5> arr = {1, 2, 3, 4, 5}; // 创建一个array,使用大括号初始化
如果你有一个初始化列表或者一个范围,你可以使用范围构造函数来初始化容器。
std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用花括号初始化vector std::list<int> lst(std::begin(vec), std::end(vec)); // 使用另一个容器的元素范围来初始化list
对于某些容器,如 std::vector
,你可以使用赋值操作符来初始化或重新初始化容器。
std::vector<int> vec; vec = {1, 2, 3, 4, 5}; // 使用花括号对vector进行赋值初始化
std::fill_n
std::fill_n
是 std::fill
的一个变体,它接受一个计数参数,将一个值赋给从起始迭代器开始的指定数量的元素。
int arr[5]; std::fill_n(std::begin(arr), 5, 1); // 将前5个元素设置为1
虽然这不是一个算法,但在某些情况下,你可能需要手动使用循环来初始化容器。
std::vector<int> vec(10); for (int i = 0; i < vec.size(); ++i) { vec[i] = i * 2; // 初始化每个元素为它的索引乘以2 }
std::generate
或 std::generate_n
这些算法可以用来生成一个值的序列,并将它们赋给容器中的元素。
std::vector<int> vec(10); std::generate(vec.begin(), vec.end(), [&] { return rand() % 100; }); // 使用 lambda 表达式生成随机数 std::generate_n(std::back_inserter(vec), 5, [&] { return rand() % 100; }); // 向vec添加5个随机数
std::copy
或 std::copy_n
如果你有一个源范围,你可以使用 std::copy
或 std::copy_n
来初始化容器。
int arr[5] = {1, 2, 3, 4, 5}; std::vector<int> vec; vec.reserve(5); std::copy(std::begin(arr), std::end(arr), std::back_inserter(vec)); // 复制arr到vec
assign
方法某些容器提供了 assign
方法,可以用来替换容器中的所有元素。
std::vector<int> vec; vec.assign({1, 2, 3, 4, 5}); // 使用初始化列表重新初始化vec
这些方法可以根据你的具体需求和场景选择使用。
std::fill
和 std::fill_n
都是C++标准库中的算法,用于初始化一系列元素,但它们在性能上的差异主要体现在使用场景和效率上:
std::fill
:
std::fill
接受两个迭代器和一个值作为参数,将迭代器范围内的所有元素设置为给定的值。std::fill_n
:
std::fill_n
接受一个迭代器、一个计数和一个值作为参数,将迭代器开始的指定数量的元素设置为给定的值。 std::fill_n
通常比 std::fill
更高效,因为它直接知道要填充的元素数量,不需要迭代到容器的末尾。这减少了迭代次数,特别是在处理大型容器时,可以显著提高性能。
std::fill
更适用于填充直到容器末尾的所有元素,而 std::fill_n
更适用于已知需要填充的元素数量,但不一定知道容器的末尾迭代器。
现代编译器可能会对 std::fill_n
进行更好的循环优化,因为它提供了明确的循环次数,这有助于编译器进行更有效的指令调度和循环展开。
两者在内存访问模式上相似,都是连续写入操作,但由于 std::fill_n
的循环次数已知,可能在某些情况下获得更好的内存访问模式优化。
- // 假设有一个非常大的容器 int value = 42;
- // 使用 std::fill
- std::vector<int> vec(1000000); std::fill(vec.begin(), vec.end(), value);
- // 使用 std::fill_n
- std::fill_n(vec.begin(), vec.size(), value);
在实际应用中,如果你知道要填充的元素数量,使用 std::fill_n
通常是更好的选择,因为它提供了更好的性能优化机会。然而,如果你需要填充直到容器末尾的所有元素,std::fill
是更合适的选择。在某些情况下,两者的性能差异可能非常小,尤其是在容器较小或编译器优化非常有效的情况下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。