5

我想要做的(使用 C++ lambda)实际上是:

std::vector<MyType> GetTheArray () {return something;}

const auto DoSomething = [](std::vector<MyType> & array)
{
     //Some processing that involves either sorting the 'array' or setting temporary flags on the items
};

DoSomething (GetTheArray ());

这在标准 C++ 中似乎是不允许的,因为右值不能作为非常量引用传递。

我的问题:

1) 有没有办法使用类型转换来做到这一点,或者我必须创建一个临时变量来存储 GetTheArray () 的结果?

2) 有充分的理由在 C++ 中不允许这样做吗?

请注意,从“GetTheArray”返回的“something”是动态构造的数组,而不是存储值。

4

5 回答 5

6

从评论看来,您想要的是获取一个向量,对其进行破坏性修改(在无法重置原始状态的意义上),然后在内部使用结果。并且您希望这对左值和右值都有效。

下一个问题是在左值的情况下,保存原始容器的代码在函数调用完成后是否需要它,以及它是否需要向量的原始状态。根据答案,您有不同的解决方案:

持有左值的调用者在调用后不再使用它

(或者,持有左值的调用者需要原始状态)

这是最简单的情况。然后你的函数应该按值获取容器。如果调用者有一个左值,它std::move可以避免复制(它不再关心对象)或可能更昂贵但保持原始容器不变的复制。

如果使用右值调用函数,则副本将被省略或转换为廉价的隐式移动。

持有左值的调用者不需要原始状态,但需要容器

这种情况很困难,您需要为同一个函数(或 lambda)提供两个重载,一个取一个左值供该调用者使用,另一个取一个右值引用,用于调用者传递一个暂时的。在这两种情况下,绑定都很便宜。虽然这需要更多代码,但您可以根据另一个重载实现一个重载:

rtype f(std::vector<Data> & );   // for lvalues
rtype f(std::vector<Data> && v)  // for rvalues
   { return f(v); }              // v is an lvalue here

你正在做 lambdas 的事实可能会使这稍微复杂一些,但希望不会太多。

于 2013-04-25T14:02:49.277 回答
3

如果您出于某种原因确实想要修改something,您可以随时将临时文件复制到您的 lambda 中。

const auto DoSomething = [](std::vector<MyType> array) { /*whatever*/ }

您将 lambda 称为编译器的方式可能能够省略副本。C++11 移动语义对此进行了形式化。

于 2013-04-25T13:41:36.433 回答
2

(实际上,@honk 在按值传递方面击败了我。不同的是,我将扩展我的答案以&&明确讨论使用)

删除&, 并通过值传递它。

您使用的是 lambdas,因此您使用的是 c++11,因此您应该只通过value传递它。是的,它会一样快。

C ++ 11 非常善于注意到“复制”临时文件的时间。它将用move替换副本。然后它会很快,并且可以说它会更容易阅读。

&&因此,即使您可能对等一无所知,但可以std::move肯定地说,您应该开始朝着通过值而不是通过引用传递事物的方向发展。它将导致代码更具可读性,并且如果在正确的时间使用它不应该导致速度变慢。

基本上,如果您将临时值(例如函数返回的值)传递给函数会很快,但前提是您使用的是标准容器,例如vector. 否则,您将需要编写自己的&&感知构造函数以利用可能的加速。

更新: 如果您决定通过引用强制它,和/或您正在使用自定义容器,那么您可以替换&&&. 这将允许您传递非常量引用。这称为rvalue-reference

正如许多其他人所指出的,临时文件将在DoSomething返回后立即销毁。请记住这一点。这意味着您将希望在数组返回之前完全使用它的内容。也许您将其打印到屏幕上,或者将其存储在数据库中。或者,您可以将数据复制或移动到另一个对象中并返回。

于 2013-04-25T13:47:19.990 回答
1

GetTheArray()您正在处理从您的底线调用的临时返回。这只能绑定到一个 const 引用,然后对象的生命周期将延长到它所绑定的 const 引用的生命周期(因此是“绑定”)。

即使你可以做你想做的事,你的电话DoSomething仍然是一个昂贵的无操作。至少你需要returnDoSomething.

C++ 禁止这样做,因为(自 C++11 起)它具有带有移动语义的右值引用,它可以做很棒的事情,但不能不返回something

于 2013-04-25T13:31:51.597 回答
0

如果需要修改something数组,则需要返回对它的引用。否则不要通过(非const)引用传递它DoSomething
不允许它的原因是为了避免您在此处说明的问题。看起来您要修改something,但something返回的副本GetTheArray()将被更改。这没有多大意义,因为此副本将在DoSomething退出后立即删除。
你有 3 种方法来解决这个问题。
1.您需要修改something然后更改GetTheArray以返回参考
2.您需要修改something将被丢弃DoSomething的副本,然后更改DoSomething为按值接受数组。3.此时
不需要something修改DoSomethingconstDoSomething应使用参考作为参数。

于 2013-04-25T13:29:36.623 回答