Whether the compiler can apply RVO depends on the actual code involved. A general guideline is to create the returned value as late as possible. For example:
std::string no_rvo(bool b) {
std::string t = "true", f = "fals";
f += t[3]; // Imagine a "sufficiently smart compiler" couldn't delay initialization
// for some reason, such not noticing only one object is required depending on some
// condition.
//return (b ? t : f); // or more verbosely:
if (b) {
return t;
}
return f;
}
std::string probably_rvo(bool b) {
// Delay creation until the last possible moment; RVO still applies even though
// this is superficially similar to no_rvo.
if (b) {
return "true";
}
return "false";
}
With C++0x, the compiler is free to make even more assumptions, principally by being able to use move semantics. How those work is a 'nother can of worms, but move semantics are being designed so that they can apply to the exact code above. This helps most dramatically in the no_rvo case, but it provides guaranteed semantics in both cases, as a move operation (if possible) is preferred over a copy operation, while RVO is completely optional and not easy to check.