我在 C++11 中使用 lambda制作了一个finally模拟器,如下所示:
#include <cstdio>
template<typename Functor>
struct Finalizer
{
Finalizer(Functor& func) : func_(func) {} // (1)
~Finalizer() { func_(); }
private:
Functor func_; // (2)
};
template<typename functor>
Finalizer<functor> finally(functor& func)
{
return Finalizer<functor>(func); (3)
}
int main()
{
int a = 20;
// print the value of a at the escape of the scope
auto finalizer = finally([&]{ printf("%d\n", a); }); // (4)
}
代码按预期工作,但在Finalizer结构 (1)的 ctor 处存在不需要的复制 ctor 调用(lambda 仿函数)。(谢天谢地,RVO 避免了finally函数 (3 -> 4) 中 return 语句的复制构造。)
编译器不会消除复制 ctor 调用(至少在 vc10 中 - gcc 可能会对其进行优化),并且如果将Finalizer struct (2) 中的仿函数类型更改为引用,它将崩溃,因为finally调用中的 lambda 参数 ( 4) 是 r 值。
当然,代码可以像下面这样“优化”
template<typename Functor>
struct Finalizer
{
Finalizer(Functor& func) : func_(func) {}
~Finalizer() { func_(); }
private:
Functor& func_;
};
int main()
{
int a = 20;
auto finalizer = [&]{ printf("%d\n", a); };
Finalizer<decltype(finalizer)> fin(finalizer);
}
没有开销,只在作用域末尾放置了一个printf调用。但是……我不喜欢。:( 我试图用宏包装它,但它需要声明两个“名称”——一个用于 lambda 对象,另一个用于终结器对象。
我的目标很简单——
- 应该消除所有可以避免的不必要的性能开销。理想情况下,不应该有函数调用,每个过程都应该内联。
- 保持简洁的表达作为效用函数的目的。允许使用宏,但不鼓励使用。
对于这种情况,有什么解决方案可以避免它吗?