是否仍然建议将函子而不是函数传递给 STL
Is it still advisable to pass functors to STL instead of functions?
在《有效的STL》中,Scott Meyers早在2001年就建议:
第 46 项:将函数对象而不是函数视为算法参数
在上述章节中,他继续解释inline operator()
可以内联到算法的主体中,但传递函数通常不能。这是因为我们实际上传递了一个函数指针。
为了支持这一点,我似乎记得,如果一个函数的地址被占用,该函数就不能内联。
所以这里有两个问题。首先,C++14 仍然如此吗?
如果是:
- 为什么没有自动执行此操作的机制(动机:声明函子比声明函数要简单得多,可读性要强得多)。
- 没有捕获的 lambda 可以转换为函数指针,而捕获 lambda 只能作为函子传递。这是否意味着我们只需要为了规定的优化而捕获某些内容?
C++14 仍然如此吗?
取决于编译器是否可以内联整个算法。如果可以,那么它也可能内联函数调用。如果不是,则函数可能无法内联,因为在这种情况下,算法是使用函数指针类型实例化的,因此必须能够处理该类型的所有函数指针。
例如,g++ 可以内联一个简单的算法,如 std::transform
但不能内联 std::sort
。
没有捕获的 lambda 可以转换为函数指针,而捕获 lambda 只能作为函子传递。这是否意味着我们只需要为了在顶部优化中陈述而捕获某些内容?
不。没有捕获的 lambda 仍然是函子;该算法使用闭包类型(lambda 的类型)而不是函数指针类型进行实例化。
为了支持这一点,我似乎记得,如果一个函数的地址被占用,该函数就不能内联。
你读错了。函数可以内联到任何直接调用站点和任何间接调用站点(如果编译器可以跟踪函数指针)。GCC 手册页所说的是,内联到每个调用站点的函数根本不会作为单独的函数发出(从而减小二进制大小),除非它的地址被占用。
首先,C++14 仍然如此吗?
是的。当然,现在您通常会编写 lambda 而不是手工制作的函子。
为什么没有自动执行此操作的机制。
这是类型系统的问题。具有给定签名的所有函数都具有相同的类型。因此,传递函数指针的算法被实例化为一个具体函数,其代码在C++的编译模型中仅存在一次。
当然,优化器仍然可以将函数专用于一个特定的参数,但这是一种比仅仅内联函子更高级的优化。所以是的,有一种机制,只是不太可能被使用。
这是否意味着我们只需要为了在顶部优化中陈述而捕获某些内容?
不。可以转换为函数指针,但除非您显式调用它,否则当您将 lambda 传递给算法时不会完成。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 有没有办法捕获 STL 函数未被赋予正确参数的异常?
- 如何在 STL 函数中找到传递给谓词的元素的索引?
- 不能对类型化模板使用 STL 函数
- 如何使用 binary_search STL 函数在嵌套类中搜索整数?
- C++ 如何将参数传递给 STL 函数
- 如何将 STL 队列推送函数绑定到 std::函数?
- STL 函数和函数类型与函数指针类型
- 接受任何 STL 容器的函数
- 重载 STL 函数
- 为什么 stl 字符串C++函数有时出错有时会出错?
- 如何将元素从 STL 队列传递到函数?
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- C++如何获取传递给函数(STL 迭代器)的参数的名称
- 为什么 STL 函数使用节点的颜色来计算 std::map 节点前身