C ++ 0x lambda vs #define

时间:2012-03-02 22:04:30

标签: c++ c++11 lambda comparison c-preprocessor

使用lambda比使用#define宏有什么好处?

我遇到过一些情况,为了方便起见我使用了lambda,但我可以很容易地使用类似的定义宏以同样的方式解决问题。

示例(随机代码)

auto dyndelay=[=]()->bool{return(mode?(queue.front().initTime+delay)<GetTickCount():TRUE);};

没有任何好处:

#define dyndelay (mode?(queue.front().initTime+delay)<GetTickCount():TRUE)

@Oli Charlesworth

#define dyndelay ....;
#define adifferentlambda ....;
#define myDefine(x) x:dyndelay:adifferentroutine
bool someCondition;

myDefine(someCondition)

5 个答案:

答案 0 :(得分:7)

你正在以完全错误的方式看待事物。 lambda是一种更通用的结构。它模拟匿名函数和闭包形式。它甚至可以使用函数对象捕获到一个公共形式,然后可以在运行时使用它来建模间接函数调用的形式(类似于函数指针或虚函数)。

宏只是一种强力文本替换机制。

然而,看起来你在语法基础上比较两者。是的,如果你想获得尽可能短的语法,那么宏就是你要走的路。它们也是毁掉你的代码的方法。事实上,我甚至可以使用宏来减少hello world,就像这样:

INCLUDE_EVERYTHING
MAIN
PRINT_HELLO_WORLD
END_BLOCK

我们可以使用预处理器以这种方式发明全新的语言!当然我们也无法有效地跟踪代码,我们抛弃了C ++(范围)的许多用处,而且没有其他人会想要阅读或使用我们的代码。但是,嘿,语法更短......

当你开始涉及泛型算法时,你会发现没有宏替换是可行的,这是使用lambda的最明显的地方之一。

vector<string> v = {...};
sort(begin(v), end(v), [](const string& str1, const string& str2){
    return str1.size() < str2.size();
});
// v is sorted based on string length starting from shortest string to longest

当然,您仍然可以不遗余力地创建所有通用算法的臃肿,残缺的版本,其中所有内容都以宏的形式实现,然后您就可以使用宏。

接下来,您可以尝试使用仅使用宏来实现信号和插槽机制,这是另一个使用lambdas的地方。

总之,我认为您需要理解为什么在C ++中不鼓励预处理器如此强烈。这是一个更普遍的主题,涉及范围,调试,混淆错误(作为纯文本替换的替代),等等。正如GMan指出的那样,试图仅基于语法来比较两者,这表明你缺乏对宏和lambdas以及他们应该服务的目的。

但公平地说,您可以使用宏创建更短的语法。毕竟,复制/粘贴式文本替换机制可以让你逃脱大量的快捷方式。但要非常清楚这样做的问题。随着您对C ++的熟悉,您会发现自己接受一些语法开销,以便在您开始使用生产代码并查看预处理器可能导致的第一手问题时避免使用宏。当你开始越来越习惯涉及通用算法(包括parallel_for)和信号和插槽等功能对象时,你也会开始更多地欣赏lambdas的真正力量。

答案 1 :(得分:4)

考虑致电someFunctionWithAnAsyncCallbackOnSuccessLikeInNodeJS(dyndelay)。这就是lambdas的力量所在:它们可以像以后任何其他对象一样存储和使用。在调用dyndelay时,宏可以传入someFunction...结果,但它无法传递{{>> 的{{em> 1}}按需调用someFunction...。当然,一个dyndelay的类会做同样的事情,我相信很多STL算法都会使用这些算法,但lambdas却不那么冗长。

(为清晰起见而编辑)。

答案 2 :(得分:3)

您可以将该宏用作对象吗?即可以这样做吗?

auto dyndelay=[=]()....;

return dyndelay;

答案 3 :(得分:3)

您可以将lambda作为仿函数传递给foreach等模板。参见例如this "How to use std::foreach" answer。这也很可能是添加lambdas的主要动机。这些事情以前都是用仿函数完成的,但代码不必要很长,需要大量的重复才能捕获值。

答案 4 :(得分:1)

宏不是该语言的一等公民。例如,宏不能作为参数传递给算法。

std::find_if(begin(a),end(b),
             [](foo const &f) { return f.v() < 10 && f.is_something() });

预处理器实际上甚至不是语言的一部分。它有一些C ++无法自行完成的工具,但对于其他所有工具,最好避免使用预处理器。

这是Herb Sutter关于lambda的讨论,以获得更多lambda的优点:

http://vimeo.com/23975522