【发布时间】:2016-04-22 15:05:24
【问题描述】:
从下面的 sn-p 中,我是否应该得出结论,std::transform 比 boost::transform 更有效,因为前者使用的初始化和析构函数比后者少?
#include <algorithm>
#include <boost/range/algorithm.hpp>
class Ftor {
public:
Ftor(const Ftor& rhs) : t(rhs.t)
{ std::cout << " Ftor : copy\n"; }
Ftor(float rate) : t(rate)
{ std::cout << " Ftor : init\n"; }
~Ftor()
{ std::cout << "~Ftor : ...\n"; }
float operator() (float x) { return x < t ? 0.0 : 1.0; }
private:
float t;
};
typedef std::vector<float> vec_t;
int main (void)
{
vec_t arg(/*...*/);
vec_t val(arg.size());
float x = 1.0;
/* Standard transform test */
std::cout << "Standard transform:\n";
std::transform(arg.begin(), arg.end(), val.begin(), Ftor(x));
std::cout << "Boost transform:\n";
/* Boost transform test */
boost::transform(boost::make_iterator_range(arg.begin(), arg.end()),
val.begin(), Ftor(x));
}
输出:
Standard transform:
Ftor : init
~Ftor : ...
Boost transform:
Ftor : init
Ftor : copy
~Ftor : ...
~Ftor : ...
标准转换使用 2 次调用。 Boost 变换使用 4 次调用。标准变换获胜。还是……?
附录
正如@sehe 建议的那样,std::ref 每次调用transform 都会保存一个构造函数,而boost::transform 只使用一次调用。但是std::ref 不能将临时变量作为参数。但是,传递Ftor f(x) 很好,因为后者有一个明确的地址。
在循环内调用 transform 时计算构造函数/析构函数调用。我现在有两个 boost 选项:
std::cout << "with std::ref\n";
for (/*...*/) {
x = ...;
f = Ftor(x);
boost::transform(arg, val.begin(), std::ref(f));
}
std::cout << "with temporary\n";
for (/*...*/) {
x = ...;
boost::transform(arg, val.begin(), Ftor(x));
}
输出:
with std::ref
Ftor : init
Ftor : init
...
~Ftor : ...
with temporary
Ftor : init
Ftor : copy
~Ftor : ...
~Ftor : ...
Ftor : init
Ftor : copy
~Ftor : ...
~Ftor : ...
...
我有一个 gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
有或没有-O3 产生相同的结果。
构造函数/析构函数是否“昂贵”是相对于operator()。它是最终产品,它将执行不太苛刻的数学运算,与上面的示例没有什么不同。
【问题讨论】:
-
编辑几乎没有意义。为什么在仿函数中甚至没有使用成员变量
t? -
return (x<t?1.:0.); -
天哪。我真的需要检查我的眼睛。无论如何,等待基准代码(或者可能是代码试图实现的目标。可能有更好的算法方法)
-
重新。编辑。 Complete example 再次计算了你不应该计算的东西。实际的基准在哪里?
标签: c++ algorithm boost transform std