Not that I don't trust my compiler, but I like to know what's going on. Let's say I have
struct Foo {
std::string s;
};
and I want to create one of those (on the stack), fill in the very long string, and return it from my function.
Foo f() {
Foo foo {my_very_long_string};
return foo;
// OR: return Foo {my_very_long_string};
}
I know there's such things as RVO and move semantics; how do I know that they're being used, and at runtime it's not allocating a new string with data on the heap, copying it, and freeing the old one? (Other than my program will get slow.)
Is it using a move constructor to reuse the string data? Or is it using RVO to actually return the same string?
In the function:
Foo f() {
Foo foo{my_very_long_string};
return foo;
}
The object foo
has a name (i.e.: foo
), it is a named object.
Named RVO (NRVO), which is an optional optimization, may occur. If no NRVO takes place, then foo
is moved, since it is a local object and therefore treated as an rvalue in this context (i.e.: the return
statement).
However, in the function:
Foo f() {
return Foo{my_very_long_string};
}
A unnamed object, which is the one resulting from Foo{my_very_long_string}
, is concerned.
As of C++17, the copy has to be necessarily elided (i.e.: same effect as RVO, although different semantics).
Before C++17, RVO, which was back then an optional optimization, may occur. If it doesn't, then it is moved, since Foo{my_very_long_string}
is already an rvalue.
No heap allocation for a new string will happen in any of the cases above.