inf*_*inf 167 c++ optimization lambda compiler-optimization c++11
The C++ Standard Library (Second Edition)Nicolai Josuttis 在其着作中指出,编译器可以比普通函数更好地优化lambdas.
此外,C++编译器比普通函数更好地优化lambdas.(第213页)
这是为什么?
我认为在内联时不应该有任何差别.我能想到的唯一原因是编译器可能有一个更好的本地上下文与lambdas,这样可以做出更多假设并执行更多优化.
Kon*_*lph 169
原因是lambda是函数对象,因此将它们传递给函数模板将实例化一个专门用于该对象的新函数.因此编译器可以简单地内联lambda调用.
另一方面,对于函数,旧的警告适用:函数指针被传递给函数模板,并且编译器传统上在通过函数指针调用调用时遇到很多问题.从理论上讲,它们可以内联,但前提是周围的函数也是内联的.
例如,请考虑以下函数模板:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
Run Code Online (Sandbox Code Playgroud)
用这样的lambda调用它:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
Run Code Online (Sandbox Code Playgroud)
此实例化中的结果(由编译器创建):
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
Run Code Online (Sandbox Code Playgroud)
...编译器知道_some_lambda_type::operator ()并且可以简单地内联调用它.(并且map使用任何其他lambda 调用该函数将创建一个新的实例化,map因为每个lambda具有不同的类型.)
但是当使用函数指针调用时,实例化如下所示:
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
Run Code Online (Sandbox Code Playgroud)
...并且这里f指向每次调用的不同地址map,因此编译器不能内联调用,f除非周围的调用map也已内联,以便编译器可以解析f为一个特定的函数.
jco*_*der 25
因为当你将"函数"传递给算法时,你实际上是在传递一个指向函数的指针,所以它必须通过指向函数的指针进行间接调用.当您使用lambda时,您将对象传递给专门为该类型实例化的模板实例,并且对lambda函数的调用是直接调用,而不是通过函数指针调用,因此更可能被内联.