c – 为什么std :: find_if(first,last,p)不通过引用获取谓词?

我正在查看 std::find_if on cppreference.com,的各种签名,我注意到采用谓词函数的风格似乎接受它的值:
template< class InputIt,class UnaryPredicate >
InputIt find_if( InputIt first,InputIt last,UnaryPredicate p );

如果我正确理解它们,带有捕获变量的lambdas会为其数据的引用或副本分配存储空间,因此大概是“按值传递”意味着会为调用复制捕获数据的副本.

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

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

第二,我对传递lambdas的理解是否正确?

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

解决方法

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

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

除此之外,lambda表达式是prvalues.意思是,使用c++17的保证副本省略,p直接从lambda表达式初始化.在将函数传递给函数时,没有额外的闭包副本或捕获的对象(函数可能会在内部制作更多副本,但这并不常见).

如果谓词是通过引用传递的,则需要实现临时对象.因此对于lambda表达式,交换机无法通过引用获取任何内容.

如果您有其他类型的谓词,这些谓词可以扩展,那么您可以将std :: reference_wrapper传递给该谓词对象,以获得便宜的“句柄”.包装器的operator()将做正确的事情.

这个定义大多是历史性的,但是现在通过价值传递来实现它并不是一个问题.

为了详细阐述为什么引用语义会很糟糕,让我们试着用它来度过这些年.一个简单的左值引用不会这样做,因为现在我们不支持绑定到右值. const lvalue引用也不会这样做,因为现在我们要求谓词不修改任何内部状态,为什么?

所以到c++11,我们真的没有其他选择.传递值优于参考值.有了新标准,我们可能会修改我们的方法.为了支持rvalues,我们可以添加一个rvalue引用重载.但这是一种冗余练习,因为它不需要做任何不同的事情.

通过传递一个值,调用者可以选择如何创建它,对于prvalues,在c++17中,它几乎是免费的.如果调用者如此期望,他们可以明确地提供引用语义.所以没有任何东西丢失,我认为在简单的使用和API设计方面获得了很多.

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...