从下面的代码段中,我可以得出结论,
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时计算构造函数/析构函数调用的情况。现在我有两个选项:
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
在函数对象中甚至都没有被使用? - sehereturn (x<t?1.:0.);
- rytis