Avoiding copy of objects with the "return" statement

moving a temporary object prevents copy elision
return a copy of an object c++
disable copy elision
c++ return object without copy constructor
std::move
move semantics
c++ avoid copy constructor
c++ avoid string copy

I have a very basic question in C++. How to avoid copy when returning an object ?

Here is an example :

std::vector<unsigned int> test(const unsigned int n)
{
    std::vector<unsigned int> x;
    for (unsigned int i = 0; i < n; ++i) {
        x.push_back(i);
    }
    return x;
}

As I understand how C++ works, this function will create 2 vectors : the local one (x), and the copy of x which will be returned. Is there a way to avoid the copy ? (and I don't want to return a pointer to an object, but the object itself)


What would be the syntax of that function using "move semantics" (which was stated in the comments)?

This program can take advantage of named return value optimization (NRVO). See here: http://en.wikipedia.org/wiki/Copy_elision

In C++11 there are move constructors and assignment which are also cheap. You can read a tutorial here: http://thbecker.net/articles/rvalue_references/section_01.html

Preventing Object Copy in C++ (3 Different Ways), Preventing Object Copy in C++ (3 Different Ways). Many times, user wants that an instance of a C++ class should not be copied at all. So, the question is how do​  The above returns a vector of three A objects where each object is value-constructed. The use of reserve() ensures no extra copies are required for expanding the result vector when the three items are added, while emplace_back() constructs the objects in place, thus avoiding an unnecessary copy or move. The main function of the previous basic example can be modified to confirm the behaviour of the helper function:

There seems to be some confusion as to how the RVO (Return Value Optimization) works.

A simple example:

#include <iostream>

struct A {
    int a;
    int b;
    int c;
    int d;
};

A create(int i) {
    A a = {i, i+1, i+2, i+3 };
    std::cout << &a << "\n";
    return a;
}

int main(int argc, char*[]) {
    A a = create(argc);
    std::cout << &a << "\n";
}

And its output at ideone:

0xbf928684
0xbf928684

Surprising ?

Actually, that is the effect of RVO: the object to be returned is constructed directly in place in the caller.

How ?

Traditionally, the caller (main here) will reserve some space on the stack for the return value: the return slot; the callee (create here) is passed (somehow) the address of the return slot to copy its return value into. The callee then allocate its own space for the local variable in which it builds the result, like for any other local variable, and then copies it into the return slot upon the return statement.

RVO is triggered when the compiler deduces from the code that the variable can be constructed directly into the return slot with equivalent semantics (the as-if rule).

Note that this is such a common optimization that it is explicitly white-listed by the Standard and the compiler does not have to worry about possible side-effects of the copy (or move) constructor.

When ?

The compiler is most likely to use simple rules, such as:

// 1. works
A unnamed() { return {1, 2, 3, 4}; }

// 2. works
A unique_named() {
    A a = {1, 2, 3, 4};
    return a;
}

// 3. works
A mixed_unnamed_named(bool b) {
    if (b) { return {1, 2, 3, 4}; }

    A a = {1, 2, 3, 4};
    return a;
}

// 4. does not work
A mixed_named_unnamed(bool b) {
    A a = {1, 2, 3, 4};

    if (b) { return {4, 3, 2, 1}; }

    return a;
}

In the latter case (4), the optimization cannot be applied when A is returned because the compiler cannot build a in the return slot, as it may need it for something else (depending on the boolean condition b).

A simple rule of thumb is thus that:

RVO should be applied if no other candidate for the return slot has been declared prior to the return statement.

C++ Class and Preventing Object Copy · ariya.io, There are three ways to prevent such an object copy: keeping the copy constructor and assignment operator private, using a special non-copyable mixin, or deleting those special member functions. A class that represents a wrapper stream of a file should not have its instance copied around. It creates a shallow copy by creating a new object and then copying the non-static members of the current object to the new object. For value type members, the bit-by-bit copy of the members is performed while for reference type members, the reference is copied but the referred object is not.

Named Return Value Optimization will do the job for you since the compiler tries to eliminate redundant Copy constructor and Destructor calls while using it.

std::vector<unsigned int> test(const unsigned int n){
    std::vector<unsigned int> x;
    return x;
}
...
std::vector<unsigned int> y;
y = test(10);

with return value optimization:

  1. y is created
  2. x is created
  3. x is assigned into y
  4. x is destructed

(in case you want to try it yourself for deeper understanding, look at this example of mine)

or even better, just like Matthieu M. pointed out, if you call test within the same line where y is declared, you can also avoid construction of redundant object and redundant assignment as well (x will be constructed within memory where y will be stored):

std::vector<unsigned int> y = test(10);

check his answer for better understanding of that situation (you will also find out that this kind of optimization can not always be applied).

OR you could modify your code to pass the reference of vector to your function, which would be semantically more correct while avoiding copying:

void test(std::vector<unsigned int>& x){
    // use x.size() instead of n
    // do something with x...
}
...
std::vector<unsigned int> y;
test(y);

How to Deep Copy Objects and Arrays in JavaScript, It is actually pretty easy to avoid needing to deep copy in JavaScript — if you can just never nest objects and arrays inside each other. Because in  When you pass an object to a function, MATLAB passes a copy of the object into the function workspace. If the function modifies the object, MATLAB modifies only the copy of the object that is in the function workspace. The differences in copy behavior between handle and value classes are important in such cases:

Compilers often can optimize away the extra copy for you (this is known as return value optimization). See https://isocpp.org/wiki/faq/ctors#return-by-value-optimization

4 different techniques for copying objects in JavaScript, We call the copy shallow because the properties in the target object can the target , which we normally pass as {} in order to prevent mutation. Deep Copying Objects. A deep copy will duplicate every object it encounters. The copy and the original object will not share anything, so it will be a copy of the original. Here's the fix to the problem we encountered using Object.assign(). Let's explore. Using JSON.parse(JSON.stringify(object)); This fixes the issue we had earlier.

copy — Shallow and deep copy operations, Assignment statements in Python do not copy objects, they create bindings between a target and an object The deepcopy() function avoids these problems by:. In addition to the Equals method, strings also provide the Compare method, which gives you information about the relative order of strings instead of just a test for equality. This method is preferable to the <, <=, > and >= operators, for the same reasons as discussed above–to avoid C# problems.

How to Construct C++ Objects Without Making Copies, This article demonstrates how to avoid making copies when constructing an object, whether the constructor takes lvalues or rvalues as  Copying an object is creating a copy of an existing object in order to modify or move the copied object without impacting the original object. Unlike C++, Java objects are not passed by value but their references are passed by value instead. Consider below code snippets, Object ob1 = new Object (); Object ob2 = ob1;

Avoiding Copies And Moves With auto, These sorts of simple examples rarely talk about how objects are or could be getting copied, moved or assigned. Since the tutorials typically  In this guide I explained two ways to copy properties from one object to another. If you face a similar situation in your projects, instead of writing multiple lines of code, you can just use these classes or extension methods to copy the needed properties from one object to the other object.

Copying Objects in JavaScript ― Scotch.io, The copy variable is pointing to the same object and is a reference to Hopefully this article helped you understand and avoid future pitfalls  The first one takes an lvalue reference (no copy), and copies it into text_ (one copy). The second one takes an rvalue reference (no copy) and moves it into text_ (no copy). To make this class simpler, we can merge those two constructors into one:

Comments
  • move semantics: www2.research.att.com/~bs/C++0xFAQ.html#rval
  • It won't necessarily create a copy. NRVO or move symantics can prevent that.
  • You can rely on your compiler for performing NRVO magic or explictly use move semantics.
  • The "copy of x which will be returned" may be constructed by moving from x, or its construction elided to become the same object as x. The semantics of the language already avoid any copies.
  • In response to your edit - you do not need to change the syntax at all. Anything which is eligible for copy elision must use move construction (if the construction is not elided altogether).
  • Should be noted that not all compilers will do this and even those that do won't all the time. It may still be worth looking into IFF the object is big, you're noting copies, and profiling shows it to be a significant bottleneck.
  • +1 for pointing out that we can avoid not only copying, but construction of redundant object and redundant assignment as well ;)
  • Re case (4), it depends on the compiler (how smart it is) and the specifics of the code. For example, with the concrete code you show a smart compiler can note that the initialization of a has no side effects, and that that declaration can be moved down under the if.
  • @Cheersandhth.-Alf: Exact, the as-if rule still stands obviously. In the general case though (out-of-line constructor), this would only be deductible with LTO enabled.
  • @MatthieuM. Does it still works if an exception is thrown ?
  • @naab: I am not quite sure I see what the problem could be? All local variables prior to the exception being thrown must be destructed, no matter where they are located (in the function frame or in the caller's function frame). So I don't see why throwing would have an impact.
  • Ah I see. Indeed I had ignored the fact that you first constructed a default y before assigning to it. Your sequence of events is right in this case, though I would recommend you just directly initialize y to avoid creating two objects where one would suffice. Sorry for the noise.
  • @MatthieuM.: I appreciate your point though. Check my answer now :)
  • Too bad the reference would immediately be illegal to use (UB). -1 for bad advice.