文章目录
- 前言
- 包装器 function及模板的低效性
- 修复问题
前言
C++提供了多个包装器(wrapper,也叫适配器adapter)。这些对象用于给其他编程接口提供更一致或更合适的接口。
bind1st
和bind2ed
就是两个适配器,它们让接受两个参数的函数能够与这样的STL算法匹配,即它要求将接受一个参数的函数作为参数。
C++提供了其他的包装器,包括:
- 模板
bind
可替代bind1st
和bind2nd
,但更灵活; - 模板
mem_fn
让我们能够将成员函数作为常规函数进行传递; - 模板
referance_wrapper
让我们能够创建行为像引用但可被复制的对象; - 包装器
function
让我们能够以统一的方式处理多种类似于函数的形式
包装器 function及模板的低效性
首先,我们来看看下面这句代码:
ret = func(x);
上面func
可能是什么呢?那么func
可能是函数名?函数指针?函数对象(仿函数对象)?也有可能
是lambda
表达式对象?所以这些都是可调用的类型!如此丰富的类型,可能会导致模板的效率低下!
例如我们用下面的代码进行验证:
template<class F, class T>
T useF(F f, T x)
{static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x);
}
double f(double i)
{return i / 2;
}
struct Functor
{double operator()(double d){return d / 3;}
};
int main()
{// 函数名cout << useF(f, 11.11) << endl;// 函数对象cout << useF(Functor(), 11.11) << endl;// lamber表达式cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;return 0;
}
运行得到以下结果:
函数模板useF()
有一个静态成员 count,可根据它的地址确定模板实例化了多少次。有3个不同的地址代表模板有3个不同的实例化。
修复问题
所以我们可以用包装器 function
来解决这个问题:
template<class F, class T>
T useF(F f, T x)
{static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x);
}
double f(double i)
{return i / 2;
}
struct Functor
{double operator()(double d){return d / 3;}
};
int main()
{// 函数名std::function<double(double)> func1 = f;cout << useF(func1, 11.11) << endl;// 函数对象std::function<double(double)> func2 = Functor();cout << useF(func2, 11.11) << endl;// lamber表达式std::function<double(double)> func3 = [](double d)->double { return d /4; };cout << useF(func3, 11.11) << endl;return 0;
}
这个时候模板就实例化了1次,所以它们的地址相同: