Learn How to Capture by Move—Marco Arena

Save to:
Instapaper Pocket Readability

[Ed.: C++11 lambdas support capturing local variables by value and by reference... but not by move. This will likely be addressed in the next standard, but in the meantime we need workarounds, usually involving a shared_ptr, to get the right behavior. In this article, Marco Arena looks at the shared_ptr approach and offers another potential helper. Observing the tradeoffs in these workarounds can instructive.]

Learn How to Capture by Move

by Marco Arena

what if I want to capture by moving an object instead of both copying and referencing? Consider this plausible scenario:

function<void()> CreateLambda()

{

    vector<HugeObject> hugeObj;

    // ...preparation of hugeObj...


    auto toReturn = [hugeObj] { ...operate on hugeObj... };

    return toReturn;

}

This fragment of code prepares a vector of HugeObject (e.g. expensive to copy) and returns a lambda which uses this vector (the vector is captured by copy because it goes out of scope when the lambda is returned). Can we do better?

"Yes, of course we can!" – I heard. "We can use a shared_ptr to reference-count the vector and avoid copying it."  ...

Continue reading...

Add a Comment

You must sign in or register to add a comment.

Comments (1)

0 0

asdf from Italy said on Dec 10, 2012 06:57 PM: Italy

This is too hackish. Lambdas need to be modified to support auxiliary variables similar to &aux; in Common Lisp lambdas. e.g.

auto runningTotal = [;unsigned soFar = 0](unsigned x) { return soFar += x; }

Then move can be implemented in a natural way:

auto foo = [=; vector<Blah> v = move(hugeVal)]() { whatever; }

I should mention that Perl has a "state" keyword which is similar to "static" but for closures. Maybe C++ can overload "static" here:

auto runningTotal = [](unsigned x) {
static unsigned soFar = 0;
return soFar += x;
}