为什么std :: find_if(first,last,p)不使用引用谓词? [英] Why does std::find_if(first, last, p) not take predicate by reference?

查看:136
本文介绍了为什么std :: find_if(first,last,p)不使用引用谓词?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看 std :: find_if的各种签名在cppreference.com上,我注意到带有谓词功能的风味似乎按值接受:

I was looking at the various signatures for std::find_if on cppreference.com, and I noticed that the flavors that take a predicate function appear to accept it by value:

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

如果我正确理解它们,则具有捕获变量的lambda会为它们的引用或数据副本分配存储空间,因此,假定传递值将意味着捕获的数据的副本将为调用而复制。

If I understand them correctly, lambdas with captured variables allocate storage for either references or copies of their data, and so presumably a "pass-by-value" would imply that the copies of captured data are copied for the call.

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

On the other hand, for function pointers and other directly addressable things, the performance should be better if the function pointer is passed directly, rather than by reference-to-pointer (pointer-to-pointer).

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

First, is this correct? Is the UnaryPredicate above going to be a by-value parameter?

第二,我对传递lambda的理解正确吗? ?

Second, is my understanding of passing lambdas correct?

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

Third, is there a reason for passing by value instead of by reference in this situation? And more to the point, is there not some sufficiently ambiguous syntax (hello, universal reference) that would let the compiler do whatever it wants to get the most performance out?

推荐答案


上面的UnaryPredicate将会是一个按值参数吗?

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

是的,这就是函数参数列表中所说的。

Yes, that's what it says in the function parameter list. It accepts a deduced value type.

除此之外,lambda表达式是prvalue。含义,用c ++ 17 的保证拷贝省略,即 p 是从lambda表达式直接 初始化的。将闭包或捕获的对象传递给函数时,不进行任何额外的复制(但是,函数在内部可以复制更多,尽管并不常见)。

Beyond that, lambda expressions are prvalues. Meaning, with c++17's guaranteed copy elision, that p is initialized directly from the lambda expression. No extra copies of the closure or the captured objects are being made when passing it into the function (the function may make more copies internally however, though that's not common).

如果谓词通过引用传递,则需要实现一个临时对象。因此,对于lambda表达式,切换到按引用传递不会获得任何好处。

If the predicate was passed by reference, a temporary object would need to be materialized. So for a lambda expression, nothing is gained by a switch to pass by reference.

如果您有其他种类的谓词(可扩展的谓词),则可以传递在该谓词对象的 std :: reference_wrapper 中,以廉价的句柄对其进行处理。包装器的 operator() 会做正确的事。

If you have other sorts of predicates, which are expansive to copy, then you can pass in std::reference_wrapper to that predicate object, for a cheap "handle" to it. The wrapper's operator() will do the right thing.

该定义主要是 具有历史意义,但如今,对于

The definition is mostly historic, but nowadays it's really a non-issue to do it with pass by value.

要详细说明为什么引用语义会很烂,让我们尝试将其贯穿多年。一个简单的左值引用不会用,因为现在我们不支持绑定到右值。常量左值引用也不会执行任何操作,因为现在我们要求谓词不要修改任何内部状态,这是为什么呢?

To elaborate on why referential semantics would suck, let's try to take it through the years. A simple lvalue reference won't do, since now we don't support binding to an rvalue. A const lvalue reference won't do either, since now we require the predicate to not modify any internal state, and what for?

最多可以,我们真的没有其他选择。通过值传递比参考传递更好。使用新标准,我们可能会修改方法。为了支持右值,我们可以添加右值引用重载。但这是一种冗余操作,因为它不需要做任何其他事情。

So up to c++11, we don't really have an alternative. A pass by value would be better than a reference. With the new standard, we may revise our approach. To support rvalues, we may add an rvalue reference overload. But that is an exercise in redundancy, since it doesn't need to do anything different.

通过传递值,调用者可以选择如何创建它,对于prvalue,在c ++ 17 ,它实际上是免费的。如果调用方愿意,他们可以显式提供引用语义。因此,没有任何损失,而且我认为在使用和API设计的简便性方面可以收获很多。

By passing a value, the caller has the choice in how to create it, and for prvalues, in c++17, it's practically free. If the caller so desires, they can provide referential semantics explicitly. So nothing is lost, and I think much is gained in terms of simplicity of usage and API design.

这篇关于为什么std :: find_if(first,last,p)不使用引用谓词?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆