Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
When I call 'foo', is the data in
mystr
copied or moved into
result
? I believe that it is moved C++11 style, but I was hoping for clarification and/or links to show that.
Thanks!
Edit: I suppose I want to know the answer to this question when compiling with g++ for c++11 or later.
–
–
–
–
Your example fall on the so-called Named Return Value Optimization, which is defined in
this paragraph of the C++11 standard
. So the compiler may elide the
copy constructor
(or
move constructor
since C++14). This elision is not mandatory.
In C++11
, if the compiler does not perform this elision, the returned string will be
copy constructed
. The returned object would be moved if it were naming a function parameter,
[class.copy]/32
(bold is mine):
When the criteria for elision of a copy operation are met or would be met save for the fact that
the source object is a function parameter
, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for
the copy is first performed as if the object were designated by an rvalue
. [...]
In C++14, this last rule has changed. It also includes the case of automatic variables
[class.copy]/32
:
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return statement is a (possibly parenthesized) id-expression that names
an object with automatic storage duration
declared in the body
or parameter-declaration-clause
of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for
the copy is first performed as if the object were designated by an rvalue
. [...]
So in your example code, and
in C++14
, if the compiler does not elide the copy/move construction, the returned string will be
move constructed
.
–
Like user4581301 said, I suspect copy elision to happen (not a move) in most implementations. For c++11 and c++14, the standard allows copy elision to happen but doesn't mandate it. In c++17, some instances of copy elision will become mandated. So, for c++11 and c++14, technically the answer depends on the implementation being used. In your case specifically, we're talking about a specific type of copy elision: return value optimization (RVO). To check whether RVO happens in your environment for your given case, you can run this code:
#include <iostream>
struct Foo {
Foo() { std::cout << "Constructed" << std::endl; }
Foo(const Foo &) { std::cout << "Copy-constructed" << std::endl; }
Foo(Foo &&) { std::cout << "Move-constructed" << std::endl; }
~Foo() { std::cout << "Destructed" << std::endl; }
Foo foo() {
Foo mystr();
return mystr;
int main() {
Foo result = foo();
My implementation opts for RVO - no move takes place.
–
Since std::string result = foo();
is an initializer, it will call the constructor rather than the assignment operator. In C++11 or newer, there is guaranteed to be a move constructor with prototype std::basic_string::basic_string( basic_string&& other ) noexcept
. On every actually-existing implementation, this moves the contents rather than copying them. Although I don’t believe the standard mandates a particular implementation, it does say this particular operation must run in constant and not linear time, which precludes a deep copy. As the return value of foo()
is a temporary rvalue, that is the constructor that will be called in this snippet.
So, yes, this code will move the string rather than copy it.
The expression in a return
statement will not always be copied, however. If you return std::string("SOMELONGVALUE");
(a programmatic constructor), the implementation is permitted to construct the result in place instead. If foo()
returns a std::string&
and returns anything other than a temporary, that will be returned by reference. (Returning a reference to a temporary that's been destroyed is, as you know, undefined behavior!) And some compilers, even before C++11, would perform copy elision and avoid creating a temporary only to copy and destroy it. Newer versions of the Standard make copy elision mandatory in most situations where it’s possible, but compilers were doing it even before that.
–
The way the most compilers implement return of a class type is to pass an extra "hidden" argument to the function that is a pointer to the memory where the value being returned should be constructed. So the called function can copy or move the return value into that memory as needed without regard to the call site.
With your example code, such a compiler could even use that same memory to hold the mystr
variable, constructing it directly there, and never using either the move or copy constructor of std::string.
In my VS2015, the compiler does invoke move ctor when returning an temp variable in such a trivial case.
class A {
public:
A(int _x) :x(_x) {}
A(const A& a) {
cout << "copy ctor." << endl;
x = a.x;
A(A&& a) {
cout << "move ctor." << endl;
x = 123;
private:
int x;
A foo() {
A temp = { 7 };
return temp; //invoke move ctor
int main() {
A a = foo();
return 0;
Besieds, whether the compiler trigger RVO depends on the
price of copying, you can see the mechanism of RVO in below:
https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/RVO_V_S_std_move?lang=en
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.