c++ - 为什么编译器可以比普通函数更好地优化 lambda?

标签 c++ optimization c++11 lambda compiler-optimization

在他的书C++ 标准库(第二版)中,Nicolai Josuttis 指出编译器可以比普通函数更好地优化 lambda。

In addition, C++ compilers optimize lambdas better than they do ordinary functions. (Page 213)

这是为什么呢?

我认为当涉及到内联时,应该不再有任何区别。我能想到的唯一原因是编译器可能有更好的本地上下文与 lambda,这样可以做出更多假设并执行更多优化。

最佳答案

原因是 lambda 是 函数对象,因此将它们传递给函数模板将专门为该对象实例化一个新函数。因此,编译器可以轻松地内联 lambda 调用。

另一方面,对于函数,旧的警告适用:函数指针被传递给函数模板,编译器传统上存在很多通过函数指针进行内联调用的问题。它们可以理论上被内联,但前提是周围的函数也被内联。

例如,考虑以下函数模板:

template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
    for (; begin != end; ++begin)
        *begin = f(*begin);
}

用这样的 lambda 调用它:

int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });

此实例化的结果(由编译器创建):

template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
    for (; begin != end; ++begin)
        *begin = f.operator()(*begin);
}

…编译器知道 _some_lambda_type::operator () 并且可以简单地内联对它的调用。 (并且使用 any 其他 lambda 调用函数 map 将创建 map 的新实例,因为每个 lambda 都有不同的类型。)

但是当使用函数指针调用时,实例化如下:

template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
    for (; begin != end; ++begin)
        *begin = f(*begin);
}

…这里 f 指向不同的地址,每次调用 map ,因此编译器不能内联对 f 的调用,除非周围有对 map 的调用也已内联,以便编译器可以将 f 解析为一个特定函数。

关于c++ - 为什么编译器可以比普通函数更好地优化 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13722426/

相关文章:

C++ 模板 : Partial template Function Specialization in template class

c++ - 为什么使用 'operator==' 时出现错误 no match for `std::find` ?

c++ - 链接/运行时不同 GCC 版本的风险?

c++ - cmake:为什么 CMAKE_CXX_STANDARD 似乎不能与 check_cxx_source_compiles 一起使用

c++ - Qt 表小部件。如何一起设置垂直标题和水平标题的含义/标题?

c++ - SetWindowsHookEx - Dll 注入(inject)错过了前几次调用

c++ - 函数返回值如何工作

algorithm - 如何优化从节点路径列表构建树?

python - 如何用 numpy 在 Cython 中表示 inf 或 -inf?

android - 在 Android 上使用 OrmLite 进行 Proguard