Using std::future to manipulate objects in C++11
There are two things that concern me in the code you offer:


The Thing instances pointed to by tA, tB, tC are leaked. In this case it looks like it would be trivial to address this by stack allocating them, and passing their address to the async calls: Thing tA; async( ... , &amp;tA);
The cross thread synchronization dependencies are not explicitly addressed. Instead it's all implicit by the way the code is written. Any mistake in the code to lead to data races. For example if in creating tB2 it called the wrong get() or pass the wrong Thing*, not only would it be the wrong value, but it might race.


I spent some time trying to figure out if proposed functionality such as Resumable Functions (pdf) would allow this to be nicer, and while I expect resumable functions would help in more general code, in your code I think a bigger problem is the factoring. Namely, since nothing uses the middle state, the code passed to the future should encompass both operations.

auto tLambdaBoth = [](const string&amp; iStr, Thing* oThing) -&gt; Thing* {
    auto pthing = tLambda(iStr, oThing);
    return tLambda(pthing-&gt;getValue(), oThing);
}


And writing this showed me a new angle on my second misgiving. The original code mixed uses of the original pointer and the pointer returned by tLambda. We know that they currently are the same pointer, but assuming that could restrict your options later. In tLambdaBoth I'd rather see return tLambda(pthing-&gt;getValue(), pthing); so why not the same in the original code?

So we can address both points together by avoiding new, and then never reusing the original object; instead it always uses the pointer that's returned from the future:

Thing tA, tB, tC;

// launch futures
std::vector&lt;std::future&lt;Thing*&gt;&gt; fut1;
fut1.emplace_back(async(launch::async, tLambda, "This is a test...A", &amp;tA));
fut1.emplace_back(async(launch::async, tLambda, "This is a test...B", &amp;tB));
fut1.emplace_back(async(launch::async, tLambda, "This is a test...C", &amp;tC));

// launch second set; using values clearly no longer in flight
std::vector&lt;std::future&lt;Thing*&gt;&gt; fut2;
for (auto&amp; fut : fut1)
{
    auto pthing = fut.get();
    fut2.emplace_back(async(launch::async, tLambda, pthing-&gt;getValue(), pthing));
}

// report results
for (auto&amp; fut : fut2)
{
    cout &lt;&lt; fut.get()-&gt;getValue() &lt;&lt; endl;
}


While I definitely like this a lot better, I'm not sure I understand your use case well enough to say whether this addresses it. Perhaps you should digest what I'm saying here, and then clarify your use case if this did not address what you were trying to determine about the validity of your approach.