我正在学习新的C ++ 11 lambda特性,这段代码究竟是如何使用lambdas计算数组(双精度)的乘积?
double product2 = accumulate(begin(doubles), end(doubles), 1.0,
[](double partialresult, double d){return partialresult*d; });
我想了解变量partialresult和d来自/去的位置。
答案 0 :(得分:1)
std :: accumulate for double的特化,将在概念上类似于以下实现(为简单起见,删除了模板参数语法):
double accumulate(
iterator_type begin, iterator_type end,
double initial, functor_type f)
{
double partialResult = initial;
while(begin != end)
partialResult = f(partialResult, *begin++);
return partialResult;
}
基本上,部分结果是每一步积累的中间结果。 d将是迭代器指向的值。
答案 1 :(得分:0)
执行此操作的旧方法是创建一个重载operator()
(称为函子或函数对象)m的类,或者使用自由函数来执行此操作:
class product
{
public:
double operator()(double a, double b) const
{
return a * b;
}
};
或简单地说:
double product(double a, double b) { return a * b; }
在引擎盖下,编译器将lambdas翻译成类似上面的形式:
class <implementation_defined_unique_name>
{
// Implementation of operator() effectively as before
};
要了解accumulate
的工作原理,查看可能的实现可能有所帮助(来自en.cppreference.com):
template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T init,
BinaryOperation op)
{
for (; first != last; ++first) {
init = op(init, *first);
}
return init;
}
这里,它只是调用提供的函数,从序列中的初始值和第一个值开始。然后它存储它,并调用函数,第一个调用的结果作为第一个参数,序列中的下一个值作为第二个参数,依此类推。
答案 2 :(得分:0)
要了解算法是如何工作的,我建议自己编写一个计算产品的代码。它可以看作以下方式
double doubles[] = { /* some initializers for the array */ };
double init = 1.0;
double acc = init;
for ( auto it = begin( doubles ); it != end( doubles ); ++it )
{
acc = acc * *it;
}
您可以将代码重写为函数
double accumulate( double *first, double *last, double init_value )
{
double acc = init;
for ( ; first != last; ++first )
{
acc = acc * *first;
}
return ( acc );
}
函数调用将显示
accumulate( begin( doubles ), end( doubles ), 1.0 );
然而标准算法std :: accumulate使用operator +而不是operator *。因此,如果您需要替换operator + for operator *,您可以按以下方式重写该函数
double accumulate( double *first, double *last, double init_value, std::multiplies<double> Op )
{
double acc = init;
for ( ; first != last; ++first )
{
acc = Op( acc, *first );
}
return ( acc );
}
如果将函数定义为模板函数,则可以使用任何二进制操作代替std :: multiplies。所以我将进一步参考标准算法。您可以使用标准二进制操作std :: multiplies
编写上面的原始代码double product2 = accumulate( begin( doubles ), end( doubles ), 1.0,
multipliers<double>() );
由于函数是模板函数,因此可以将std :: multipliers替换为lambda表达式
double product2 = accumulate(begin(doubles), end(doubles), 1.0,
[](double partialresult, double d){return partialresult*d; });
如果我们为lambda表达式指定一个名称
,可以写得更清楚auto multipliers = [](double partialresult, double d){return partialresult*d; };
当算法的调用看起来
double product2 = accumulate(begin(doubles), end(doubles), 1.0,
multipliers() );
在其体内而不是标准函数对象std :: multipliers中,将调用lambda表达式的运算符函数。