Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning Large Objects in Functions

Tags:

c++

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.

like image 788
swongu Avatar asked Apr 15 '09 19:04

swongu


People also ask

How do you return objects from functions?

A function can also return objects either by value or by reference. When an object is returned by value from a function, a temporary object is created within the function, which holds the return value. This value is further assigned to another object in the calling function.

Can you return an object from a function give an example?

Returning Object as argumentobject = return object_name; Example: In the above example we can see that the add function does not return any value since its return-type is void. In the following program the add function returns an object of type 'Example'(i.e., class name) whose value is stored in E3.

Can a function return object to another function?

We must use a return keyword to return this object and return the obj created. We must create a variable myObj and then call the returnObj function. After we call this function, whatever the function will return (in this case, an object) will be stored inside the myObj variable.


1 Answers

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.

like image 96
David Rodríguez - dribeas Avatar answered Sep 21 '22 17:09

David Rodríguez - dribeas