Will returning a const object from a function prevent move construction from outside?
In your case, returnedStr
will be move-constructed from the return value of GetString()
, but that return value will be copy-constructed from str
(1). If str
wasn't const
, the return value would be move-constructed from it.
Note that in both cases, return value optimisation is still applicable, so the compiler can still construct the return value (or even str
itself) directly in the space of returnedStr
, skipping one or both copy/move constructions. This is granted by C++11 12.8/31:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
in a
return
statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value...
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
The first bullet point covers the elision of the return value construction, the other one covers moving the return value into returnedStr
. Notice the requirement on "the same cv-unqualified" type, which means that this works regardless of cv qualifiers.
(1) Note that if we were talking about a class X
other than std::string
, one which provided a move constructor taking a const X&&
, then indeed the return value would be move constructed using this constructor (whatever semantics it might have).
Angew's answer is right but who can remember all the language lawyer rules?
To help me remember it easier I wrote the following rules which came from STL's own mouth.
- Don't return locals as const [16]
$ Inhibits move semantics
- Don't use move when returning local by value of exact same type [16]
$ NVRO won't be used if you do this.
- Don't return by Rvalue reference (&&) [16]
$ Unless you really really know what you're doing.
Notes:
[16] Don't Help the Compiler, Going Native 2013, http://www.youtube.com/watch?v=AKtHxKJRwp4