Returning Large Objects in Functions

c++

Solution

The second approach is more idiomatic, and expressive. It is clear when reading the code that the function has no preconditions on the argument (it does not have an argument) and that it will actually create an object inside. The first approach is not so clear for the casual reader. The call implies that the object will be changed (pass by reference) but it is not so clear if there are any preconditions on the passed object.

About the copies. The code you posted is not using the assignment operator, but rather copy construction. The C++ defines the return value optimization that is implemented in all major compilers. If you are not sure you can run the following snippet in your compiler:

#include <iostream>
class X
{
public:
    X() { std::cout << "X::X()" << std::endl; }
    X( X const & ) { std::cout << "X::X( X const & )" << std::endl; }
    X& operator=( X const & ) { std::cout << "X::operator=(X const &)" << std::endl; }
};
X f() {
    X tmp;
    return tmp;
}
int main() {
    X x = f();
}

With g++ you will get a single line X::X(). The compiler reserves the space in the stack for the x object, then calls the function that constructs the tmp over x (in fact tmp is x. The operations inside f() are applied directly on x, being equivalent to your first code snippet (pass by reference).

If you were not using the copy constructor (had you written: X x; x = f();) then it would create both x and tmp and apply the assignment operator, yielding a three line output: X::X() / X::X() / X::operator=. So it could be a little less efficient in cases.

Problem

Compare the following two pieces of code, the first using a reference to a large object, and the second has the large object as the return value. The emphasis on a "large object" refers to the fact that repeated copies of the object, unnecessarily, is wasted cycles. Using a reference to a large object: ``` void getObjData( LargeObj& a ) { a.reset() ; a.fillWithData() ; } int main() { LargeObj a ; getObjData( a ) ; } ``` Using the large object as a return value: ``` LargeObj getObjData() { LargeObj a ; a.fillWithData() ; return a ; } int main() { LargeObj a = getObjData() ; } ``` The first snippet of code does not require copying the large object. In the second snippet, the object is created inside the function, and so in general, a copy is needed when returning the object. In this case, however, in `main()` the object is being declared. Will the compiler first create a default-constructed object, then copy the object returned by `getObjData()`, or will it be as efficient as the first snippet? I think the second snippet is easier to read but I am afraid it is less efficient. Edit: Typically, I am thinking of cases `LargeObj` to be generic container classes that, for the sake of argument, contains thousands of objects inside of them. For example, ``` typedef std::vector<HugeObj> LargeObj ; ``` so directly modifying/adding methods to `LargeObj` isn't a directly accessible solution.

Original source

Related problems