View Full Version : [C++] Returning Vector from Function
TreeFinger
December 17th, 2007, 09:51 PM
Hello, I am currently fixing up a program I handed in for homework. Well the semester is over now, this program is from the very last homework. Anyways, I want to work this bug out, but just for myself because I don't think my teacher cares anymore since he already gave grades out.
What I need to know is if I am returning a vector from a function what does it get returned to? An assignment statement ( assigning it to another vector? )?. The program needs to know the values inside this vector and the number of elements that are present in the vector. I know that the vector object ( is that what it is called? ) will be able to tell me how many elements are in the vector.. I guess my question is: How do I get the vector(and contents) from a 'vector<int> function', back to the main function?
yabbadabbadont
December 17th, 2007, 09:58 PM
You would be better off passing back a reference to a vector, rather than a copy of one. However, you should be able to just assign it to a "vector<int>" variable. The copy constructor should handle the rest for you.
aks44
December 17th, 2007, 10:53 PM
std::vector<int> foo()
{
std::vector<int> v;
/* fill it */
return v; // (1)
}
void bar()
{
std::vector<int> v = foo(); // (2)
v = foo(); // (3)
}
What really happens here?
First off, despite the apparent notation line (2) really is a copy constructor, and not a default constructor + assignment. This is mandated by the standard, and that's the reason why I used both examples (2) and (3).
So...
(2) call foo
(1) copy constructor
(back to 2) copy constructor again (ouch!)
(3) call foo
(1) copy constructor
(back to 3) assignment operator, which is usually implemented as a copy constructor (ouch again!) + swap
So as you can see, the problem is that returning an object will trigger a copy. Most modern compilers have an optimization called "Return Value Optimization" (RVO for short) which is most of the time able to merge the steps (1) and (back to...). But as with any compiler optimization you shouldn't really count on that...
That leaves us with at least one copy, which could easily be avoided:
void foo(std::vector<int>& retVal)
{
std::vector<int> v;
/* fill it */
retVal.swap(v); // (1)
}
void bar()
{
std::vector<int> v; // (2)
foo(v); // (3)
}
Now we're left with:
(2) default constructor, quite lightweight to say the least
(3) call foo
(1) swapping both vectors, again hyper lightweight
(back to 3) nothing more :)
So as yabbadabbadont put it, the best way to pass big objects back from the callee to the caller obviously is to use a reference argument.
Although this doesn't really matter for small datasets, returning vectors or other containers from a function can quickly introduce huge overhead when the dataset grows (since it involves copying the whole dataset at least once).
Which leads me way off topic:
A class supporting copy / assignment should always have a swap() method too...
- the copy constructor just does its job
- the swap method quickly and safely (as in nothrow-guarantee) exchanges the contents of two objects
- the assignment operator is implemented in terms of copy + swap (after checking for self-assignment of course)
This way you end up with an exception-safe assignment operator for almost no effort, and many use cases can be optimized away thanks to the swap() method. It's a win-win... :)
vBulletin® v3.7.4, Copyright ©2000-2008, Jelsoft Enterprises Ltd.