从0到n-1生成数字的惯用方法是什么?

时间:2014-02-03 17:11:58

标签: c++ vector idioms idiomatic

用于生成从0到n-1,任意类型,数组或向量中的数字的可接受的C ++习惯用语是什么?

换句话说,我该怎么写:

template <typename T> vector<T> generate_integers_upto(size_t n);

template <typename T> T* generate_integers_upto(size_t n);

4 个答案:

答案 0 :(得分:3)

惯用的方式是按价值返回。为简单起见,您可以使用std::iota填充向量,但这是次要的:

#include <vector>
#include <numeric>

template<typename T>
std::vector<T> generate(std::size_t n)
{
  std::vector<T> v(n);
  std::iota(std::begin(v), std::end(v), T());
  return v;
}

答案 1 :(得分:2)

只需按值返回,让编译器决定什么(RVO,移动返回等)更有效:

template<typename T>
std::vector<T> generate( std::size_t n , T begin = 0u )
{
    std::vector<T> result( n );

    std::iota( std::begin( result ) , std::end( result ) , begin );

    return result;
}

请注意,默认返回类型为unsigned int。当然,您可以更改传递给函数的值以更改返回值,或者明确指定返回类型:

int main()
{
    auto sequence = generate<float>( 100 );
}

此实现基于std::iota()标准库算法。

答案 2 :(得分:1)

这取决于你想用这些数字做什么。

如果确实想要一个范围而不是容器,那么boost::irange就足够了。它甚至不需要任何[实质性]记忆!

lets you do cool stuff like this

#include <iostream>
#include <boost/range/irange.hpp>

using boost::irange;
using std::cout;

int main()
{
    for (auto i : irange(0, 42))
        cout << i << ' ';
}

// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

答案 3 :(得分:0)

如果您希望函数为您创建数组,请按值返回std::vector

正如你的第一个例子所做的那样,返回一个引用要么无效(如果向量是一个现在被破坏的局部变量),要么是奇怪且容易出错(因为现在某个地方需要以某种方式进行管理)。

返回一个指针(可能是一个已分配的数组)容易出错,因为没有什么可以确保调用者正确地释放它。

更灵活的选择是采用迭代器范围。为两个迭代器重载它可能是有意义的:

std::vector<int> v(10);       // non-empty vector
generate(v.begin(), v.end()); // replace existing elements

和迭代器和大小:

std::vector<int> v;             // empty vector
generate(back_inserter(v), 10); // insert new elements

请注意,C ++ 11库有一个std::iota,其作用类似于第一个版本(可用于实现其中任何一个版本),但不像第二个版本。