15

I have a function that returns an array like this:

vector<string> GetString()
{
   vector<string> s;
   s.push_back("one");
   s.push_back("two");
   s.push_back("three");
   return s;
}

and I'm calling it in this way:

   vector<string> mystrings=GetStrings();

I can implement it as follows too:

void GetString(vector<string> & s)
{
   s.push_back("one");
   s.push_back("two");
   s.push_back("three");
}

and call it in this way:

 vector<string> mystrings;
 GetStrings(mystrings);

Which one is better?

Does version one copy a vector to another? If yes then it is slow if the vector is big.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
mans
  • 17,104
  • 45
  • 172
  • 321
  • Just return it, the copy will most likely be elided, and the code is cleaner. – juanchopanza Oct 22 '13 at 13:39
  • 6
    These functions do different things (build a new vector vs. extend an existing one). If you want to build a new one, then return it, by value. If you want to extend an existing one, then take it by reference. – Cubbi Oct 22 '13 at 13:39
  • First way is better. No it's not slow. – Simple Oct 22 '13 at 13:39
  • [Want speed? Pass by value.](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) (Google the phrase for mirrors in case the original article is down; happens to it quite often). – Angew is no longer proud of SO Oct 22 '13 at 13:44
  • @Angew [*"Technically there's nothing wrong with that article. However it leaves the wrong impression: Always copy by value is terrible advice. (Howard Hinnant)"*](http://stackoverflow.com/questions/18303287/when-is-overloading-pass-by-reference-l-value-and-r-value-preferred-to-pass-by#comment26858169_18303787) And I couldn't agree more. – Ali Oct 22 '13 at 15:21
  • @Ali I must admit that's not the impression I got from the article. My take-home message was "if you're going to copy your arguments anyway, take them by value instead (and `std::move()` from the parameter to the actual destination). And don't be over-afraid of returning by value." – Angew is no longer proud of SO Oct 23 '13 at 06:38

2 Answers2

19

Which one is better?

They do different things. Use the first if you want a vector containing just those strings; use the second if you want to be able to append those strings to an existing vector.

If you want the semantics of the first version, then that's "better" in the sense of being easier to use correctly, and harder to use incorrectly.

Is version one copies a vector to another?

In modern C++, definitely not: returning a local variable and initialising from a temporary are both done by moving, not copying. Even if you're stuck with a pre-C++11 compiler, both copies should be elided. If your compiler doesn't support move semantics or copy elision, then you really should throw it away.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • However I accept it as answer, but still I can not understand: The objects are created in stack, and after returning back from function, the stack on which the objects are created roll back, so we need a copy. How can we roll back the stack and eliminating copy and use move? What moves means here and how it is done? – mans Oct 22 '13 at 19:17
  • 2
    @mans: copy elision means that the object is created in the caller's stack frame, so it doesn't need to be copied on return. Moving means that the vector's contents are transferred to another by updating their internal pointers, not by copying the elements. Any decent compiler should support elision, but it isn't mandatory. All C++11 compilers must support move semantics. – Mike Seymour Oct 22 '13 at 21:41
3

This is largely an issue of personal preference, and whatever coding conventions you may be required to work with.

Prior to C++11, the second approach would sometimes have been considered preferable. The performance is guaranteed to be good because there is no unnecessary copying. The first approach, on the other hand, has the potential (in theory) to invoke a fairly expensive copy constructor.

In practice though, an optimisation called copy elision often avoids the copy constructor, meaning the performance is just as good either way. It's not guaranteed though, as it can depend on factors such as compiler settings/capabilities.

C++11 introduced move semantics though. It offers an alternative way to eliminate the copying, and is built-in to the language specification (rather than being an optional compiler optimisation). From a readability point-of-view, that can make the first option preferable, as it's perhaps more obvious what your code is doing.

Peter Bloomfield
  • 5,578
  • 26
  • 37