c++ - 为什么 std::find_if(first, last, p) 不采用引用谓词?

标签 c++ pass-by-value stl-algorithm c++17

我正在查看 std::find_if on cppreference.com, 的各种签名。我注意到采用谓词函数的 flavor 似乎按值接受它:

template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last,
             UnaryPredicate p );

如果我理解正确的话,带有捕获变量的 lambdas 会为其数据的引用或拷贝分配存储空间,因此“按值传递”可能意味着为调用复制捕获数据的拷贝。

另一方面,对于函数指针和其他可直接寻址的东西,如果直接传递函数指针,而不是通过引用指针(pointer-to-pointer)传递,性能应该会更好。

首先,这是正确的吗?是UnaryPredicate以上将是一个按值参数?

其次,我对传递 lambda 的理解是否正确?

第三,在这种情况下是否有理由通过值而不是引用传递?更重要的是,是否没有一些足够模糊的语法(你好,通用引用)可以让编译器做任何它想要获得最大性能的事情?

最佳答案

Is the UnaryPredicate above going to be a by-value parameter?



是的,这就是它在函数参数列表中所说的。它接受推导的值类型。

除此之外,lambda 表达式是纯右值。含义,与 的保证复制省略,即 p直接从 lambda 表达式初始化。将闭包或捕获的对象传递给函数时不会生成额外的拷贝(但是,该函数可能会在内部生成更多拷贝,尽管这并不常见)。

如果谓词是通过引用传递的,则需要物化一个临时对象。因此,对于 lambda 表达式,通过引用传递的开关不会获得任何东西。

如果您有其他种类的谓词,它们可以复制,那么您可以传入 std::reference_wrapper到那个谓词对象,以获得它的廉价“句柄”。包装的 operator() 会做正确的事。

该定义主要是历史性的,但现在通过值(value)传递确实不是问题。

为了详细说明为什么引用语义会很糟糕,让我们尝试通过这些年。一个简单的左值引用是行不通的,因为现在我们不支持绑定(bind)到右值。一个 const 左值引用也不行,因为现在我们要求谓词不修改任何内部状态,那是为了什么?

直到 ,我们真的别无选择。按值传递会比引用更好。有了新标准,我们可能会修改我们的方法。为了支持右值,我们可以添加一个右值引用重载。但这是一种冗余练习,因为它不需要做任何不同的事情。

通过传递一个值,调用者可以选择如何创建它,对于纯右值,可以在 中选择。 ,它实际上是免费的。如果调用者愿意,他们可以显式地提供引用语义。所以没有任何损失,而且我认为在使用简单性和 API 设计方面获得了很多。

关于c++ - 为什么 std::find_if(first, last, p) 不采用引用谓词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62536575/

相关文章:

c++ - 在 C++ 中如何使用另一个类的属性

c++ - 介入时如何跳过VS 2008中的常见类(class)?

c - 更新函数中的指针

java - java中如何交换整数类型

c++ - 可以用 0 计数调用 std::search_n 吗?

c++ - 获得 C++ std::bitset 的最低设置位的最快方法是什么?

c++ - 在 Windows 上的 Netbeans 中设置 Mysql C++ 连接器

java - java 中对象与原始传递如何工作(在集合的上下文中)?

c++ - 如何绑定(bind)一个容器中的元素以调用另一个容器中的成员函数

c++ - 使用参数 vector 并行调用元素 vector 的成员函数