athos athos - 23 days ago 9
C++ Question

is it ok to return a local variable by move?

I'm reading Nicolai M. Josuttis's 2nd edition of "The C++ Standard Library" covering C++11 , where in Chapter 18: Concurrency, page 969 and 970 give a sample program:

// concurrency/promise1.cpp
#include <thread>
#include <future>
#include <iostream>
#include <string>
#include <exception>
#include <stdexcept>
#include <functional>
#include <utility>
void doSomething (std::promise<std::string>& p)
{
try {
// read character and throw exceptiopn if ’x’
std::cout << "read char (’x’ for exception): ";
char c = std::cin.get();
if (c == ’x’) {
throw std::runtime_error(std::string("char ")+c+" read");
}
...
std::string s = std::string("char ") + c + " processed";
p.set_value(std::move(s)); // store result
}
catch (...) {
p.set_exception(std::current_exception()); // store exception
}
}

int main()
{
try {
// start thread using a promise to store the outcome
std::promise<std::string> p;
std::thread t(doSomething,std::ref(p));
t.detach();
...
// create a future to process the outcome
std::future<std::string> f(p.get_future());
// process the outcome
std::cout << "result: " << f.get() << std::endl;
}
catch (const std::exception& e) {
std::cerr << "EXCEPTION: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "EXCEPTION " << std::endl;
}
}


Here
string
s
is a local variable but moved to return.

However, as programs quited calltree level by level, the stack memory will be release. Would this be a problem when call stack unwinds?

Note: this question is different from c++11 Return value optimization or move? : this question is about
move
is potentially dangerous, while the other question is about whether actively prohibits copy elision or let compiler decide.

Answer

Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. Valid means it can be safely destroyed (e.g on stack unwinding). In your example s is not returned but stored in promise but if it was returned in normal way return s; compiler could implicitly call return move(s);.