2011-05-03 87 views
4

假设您想用随机数填充向量。然后有一个下列显而易见的解决方案:通过STL或Boost引入伪参数

vector<int> result; 
result.resize(n); 
for (int i = 0; i < n; ++i) { 
    result[i] = generateRandomNumber(); 
} 

OK,它显然作品,但我想了解什么是最简单的STL /升压方式摆脱的for循环。使用std :: transform很诱人,但它只需要一个带有一个参数的函数。有没有什么好的STL方法在函数中引入虚拟参数?

回答

5

C++标准库有std::generate()std::generate_n();

例如:

#include <iostream> 
#include <cstdlib> 
#include <algorithm> 
#include <vector> 
#include <iterator> 
int generateRandomNumber() 
{ 
    return std::rand(); 
} 
int main() 
{ 
    int n = 10; 
    std::vector<int> result; 
    generate_n(back_inserter(result), n, generateRandomNumber); 
    copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << '\n'; 
} 

测试:https://ideone.com/5xD6P

至于第二个问题,如果我理解正确,是如何创造一个仿函数接受一个int参数,忽略它,并呼吁你的int f()

C++ 98方法是实际写全算符:

struct IgnoreArgument 
{ 
    typedef int(*fp_t)(); 
    fp_t fp; 
    IgnoreArgument(fp_t f) : fp(f) {} 
    int operator()(int) const { return fp(); } 
}; 
... 
transform(v.begin(), v.end(), v.begin(), IgnoreArgument(f)); 

测试:https://ideone.com/DTsyl

C++ 11的方法是使用一个lambda表达式

transform(v.begin(), v.end(), v.begin(), [](int){return f();}); 

测试:https://ideone.com/nAPXI

而C++ 98/boost的方式是使用boost::bind

transform(v.begin(), v.end(), v.begin(), boost::bind(f)); 

测试:https://ideone.com/cvd88

+0

非常感谢。但有关虚拟变量的问题仍然存在。 – 2011-05-03 18:28:15

+0

@Ilya Razenshteyn你可以举一个如何使用这种变量的例子吗? – Cubbi 2011-05-03 18:31:18

+0

假设我有一个函数int f(),现在我想要产生一个函数int g(int){return f(); }使用标准的东西。 – 2011-05-03 18:39:12

1

使用generate_n与你有多少元素需要,具有back_insert_iterator到您想要的地方存储的向量一起,和一个指针生成号码功能。

#include <vector> 
#include <algorithm> 


int generateRandomNumber() 
{ 
    static int i = 0; 
    return 42 + (i++); 
} 

int main() 
{ 
    std::vector<int> vi; 
    std::generate_n(back_inserter(vi), 10, &generateRandomNumber);  
} 

注意,通过使用back_insert_iterator像我一样在这里,您不必预先尺寸的载体,它是缺憾的最好的。

+0

由于性能问题,我需要预先设置它的大小。 – 2011-05-03 18:38:20

+0

@Ilya:然后用'.begin()' – 2011-05-03 18:39:25

+0

替换我的示例中的'back_inserter'谢谢,但是,关于虚拟变量的问题仍然是开放的。找到它真是太棒了。 – 2011-05-03 18:41:03

1

这里的问题是,transform只是不是手头任务的正确选择。 transform的意图是采取一些输入,以某种规定的方式对每个输入进行变换,并为每个输入产生一个输出。

在这种情况下,你不要任何输入。 transform如果向量中的值基于某种现有向量中的值(以某种方式或其他方式),那么这将是有意义的。

generate_n真的是这个问题的正确解决方案 - 它打算调用N次函数/函子,生成N个结果,并将它们分配给您提供的输出迭代器(及其后继器)。由于它旨在生成值(而不是转换现有值),因此函数/函子不会接受输入,并且不必提供“假”输入。

就“虚拟”的论点而言,想要/需要它可能是一个非常好的迹象(在这种情况下)你使用了错误的算法,而不应该这样做。

但是,您确实有时会遇到相反的情况:您想使用不提供算法提供参数,但您希望能够提供参数。例如,假设您希望能够将阵列中的数字设置为随机数,并且用户指定了一些较低和/或上限。在这种情况下,您希望能够指定将传递给您的随机数函数的边界,但generategenerate_n都没有任何规定来执行此操作。

在这种情况下,您有两种可能性。一个是bind(原来是boost::bind,但现在包含在C++ 11中)。我通常喜欢使用函子,并将参数传递给ctor:

class gen_random { 
    int lower; 
    int upper; 
public: 
    gen_random(int lower = 0, int upper = RAND_MAX) : lower(lower), upper(upper) {} 

    int operator() { return rand_range(lower, upper); 
}; 

int main() { 
    std::vector<int> rand_ints; 

    std::generate_n(std::back_inserter(rand_ints), 10, gen_random(1, 6)); 
    return 0; 
}