5

(C++ ラムダを使用して) 私がやりたいことは効果的に次のとおりです。

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 ());

右辺値を非 const 参照として渡すことができないため、これは標準 C++ では許可されていないようです。

私の質問:

1) 型キャストを使用してこれを行う方法はありますか、または GetTheArray () の結果を格納するために一時変数を作成する必要がありますか?

2) これが C++ で許可されていない正当な理由はありますか?

「GetTheArray」から返される「何か」は、格納された値ではなく、その場で構築される配列であることに注意してください。

4

5 に答える 5

6

コメントから、ベクトルを取得し、破壊的に変更して (元の状態をリセットできないという意味で)、内部で結果を使用することが必要であることがわかります。そして、これが左辺値と右辺値の両方に対して効率的に機能することを望みます。

次の問題は、左辺値の場合、関数呼び出しが完了した後に元のコンテナーを保持するコードがそれを必要とするかどうか、およびベクトルの元の状態が必要かどうかです。その答えに応じて、さまざまな解決策があります。

左辺値を保持している呼び出し元は、呼び出し後にそれを使用しません

(または、左辺値を保持している呼び出し元には元の状態が必要です)

これは最も単純なケースです。次に、関数はコンテナーを値で受け取る必要があります。呼び出し元が左辺値を持っている場合、コピーstd::moveを回避するか (オブジェクトを気にしなくなります)、コストがかかる可能性がありますが、元のコンテナーはそのままにしておくことができます。

関数が右辺値で呼び出された場合、コピーは省略されるか、安価な暗黙の移動に変換されます。

左辺値を保持する呼び出し元には元の状態は必要ありませんが、コンテナーが必要です

このケースは難しいケースであり、同じ関数 (またはラムダ) に対して 2 つのオーバーロードを提供する必要があります。1 つはこの呼び出し元が使用する左辺値を取り、もう1 つは呼び出し元が一時的。どちらの場合も、バインディングは安価になります。これにはより多くのコードが必要ですが、一方のオーバーロードをもう一方の観点から実装できます。

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

ラムダを実行しているという事実により、これが少し複雑になる可能性がありますが、あまり複雑ではないことを願っています。

于 2013-04-25T14:02:49.277 に答える
3

何らかの理由で本当に変更したいsomething場合は、いつでも一時的なものをラムダにコピーできます。

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

ラムダをコンパイラと呼ぶ方法により、コピーを省略できる場合があります。C++11 の移動セマンティクスはこれを形式化します。

于 2013-04-25T13:41:36.433 に答える
1

GetTheArray()一番下の行で、通話から一時的に返されたものを処理しています。これは const 参照にのみバインドでき、オブジェクトの有効期間は、バインド先の const 参照の有効期間まで延長されます (したがって、「バインディング」)。

やりたいことができたとしても、 への呼び出しDoSomethingはコストのかかる no-op になります。少なくとも、からreturn何かをする必要がありますDoSomething

C++ はこれを禁止しています (C++11 以降) 移動セマンティクスを備えた右辺値参照があり、素晴らしいことを実行できますが、何かを返さないわけではありません。

于 2013-04-25T13:31:51.597 に答える