Difference between std::generate and std::generate_n

本文介绍了如何使用C++ STL中的std::generate和std::generate_n函数来高效地生成连续序列。对比了两种方法的不同应用场景及优缺点,并给出了具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
1. 问题:
   常常,我们编写C++程序时,需要产生 前 n 个连续的 序列:例如:1-10, 3-20 等等序列,


2. 方案
 马上想到的解决方案是:自定义一个按照顺序产生序列的 Generator,然后调用std::generate函数来产生序列并存储至容器中。


3. 资源:
  STL为我们提供了 2个generate 函数:std::generate 和 std::generate_n。如下是两个函数的声明:


   1. template <class ForwardIterator, class Generator>
   void generate(ForwardIterator first, ForwardIterator last, Generator gen);
   2. template <class OutputIterator, class Size, class Generator>
   OutputIterator generate_n(OutputIterator first, Size n, Generator gen);


  3.1 资源说明:


  相同:两个函数都是:在一个range 内,每次调用Generator生成一个值,输出到指定的Iterator指向的range 中;


   区别:两个函数需要的range不一样,

    std::generate需要两个 ForwardIterator来提供range,输入和输出range都是[First, Last),所以在输入Iterator存在之前,Container的实际内容必须存在;generator实际执行的是覆盖操作(overwrite);而不是 insert操作.


   反观std::generate 需要的参数是 OutputIterator 和 一个 N;输入range为:[0, N),输出range为:[OutputIterator, OutputIterator+N);此时输入range不需要Conatiner的存在就可以确定,所以Container的实际内容不需要存在;另外,STL提供了Insert Adapter for OutputIterator,使用Inserter,即可添加新序列至container中。


4. 结论:
  在使用变长容器时,使用 std::generate_n (Insert Adapter , N, Gen)可以提高效率。
  使用固定长度的容器时,容器的值肯定存在,两个函数的效率没区别;但是generate对容器提供的Iterator要求是:ForwardIterator 或其强化(refinement)


 

### C++ 中 `std::generate` 函数的用法 `std::generate` 是 C++ 标准库中的一个算法,用于填充容器的内容。该函数接受两个迭代器范围以及一个生成器函数或可调用对象作为参数,并依次对该范围内每个元素赋值。 语法如下: ```cpp #include <algorithm> #include <vector> namespace { template<typename ForwardIt, typename Generator> void generate(ForwardIt first, ForwardIt last, Generator g); } ``` 此函数会反复调用给定的生成器 `g()` 并将返回的结果存储到 `[first, last)` 范围内的每一个位置上[^1]。 下面是一个简单的例子来展示如何使用 `std::generate` 来初始化向量中的元素: ```cpp #include <iostream> #include <vector> #include <algorithm> // For std::generate #include <functional> // For std::ref // A simple generator function that increments an internal counter each time it's called. class CounterGenerator { private: int value; public: explicit CounterGenerator(int startValue = 0) : value(startValue) {} int operator() () { return ++value; } }; void demonstrateGenerateWithFunctionObject() { std::vector<int> numbers(5); CounterGenerator gen; std::generate(numbers.begin(), numbers.end(), gen); for (auto num : numbers) { std::cout << num << ' '; } // Output should be something like: 1 2 3 4 5 } /// Using lambda expression as a generator with std::generate void demonstrateGenerateWithLambdaExpression() { std::vector<std::string> names{"Alice", "Bob"}; auto randomNamePicker = [&names]() -> std::string& { static thread_local std::mt19937 rng(std::random_device{}()); std::uniform_int_distribution<> dist(0, names.size()-1); return names[dist(rng)]; }; std::vector<std::reference_wrapper<const std::string>> selectedNames(3); std::generate(selectedNames.begin(), selectedNames.end(), std::cref(randomNamePicker())); for(auto&& nameRef : selectedNames){ std::cout<<nameRef.get()<<'\n'; } } ``` 上述代码展示了两种不同类型的生成器:一个是类成员函数重载了 `operator()` 的方式;另一个则是通过 Lambda 表达式实现随机选取字符串的功能。这两种方法都可以很好地配合 `std::generate` 使用[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值