1

I want to pass a huge stl vector into a function in C++, when I do pass by value, does it make a copy of the huge vector internally? I'm not clear how pass by value and pass by reference differ in terms of memory allocation. Is pass-by-reference more memory efficient? Should I pass just a pointer of that huge vector into the function so that I save a lot of memory?

Could someone explain to me the difference in terms of memory for the following three cases? Assume obj is huge.

1. func(vector<obj> )

2. func(vector<obj>*) 

3. func(vector<obj*>)
Logan Yang
  • 2,364
  • 6
  • 27
  • 43
  • http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value http://stackoverflow.com/questions/270408/is-it-better-in-c-to-pass-by-value-or-pass-by-constant-reference – Nemanja Boric Sep 24 '13 at 23:02
  • 3 is not passing the same thing as 1 and 2. You need different vector for it, so it's not identical (it would alternatively be 4th option vector*). First two options have been discussed in detail already, i.e., links above. – sashkello Sep 24 '13 at 23:03
  • Just fyi, neither is pass by value here. – Luchian Grigore Sep 24 '13 at 23:16
  • 1
    ^ reference, I meant to say "neither is pass by reference" – Luchian Grigore Sep 24 '13 at 23:29

1 Answers1

8

Your third option is totally different than the first two. The type is different. I'm going to talk about the first two options (and present some more).

func(vector<obj> ) - pass by value

Changes made internally are not reflected on the outside. Theoretically, a copy is made, yes. However, the semantics are different. You couldn't pass by value and achieve the same thing. Also, with move semantics in C++11, a situation where a pass-by-value and pass-by-reference behave the same has the same efficiency, because the vector isn't copied, but moved.

func(vector<obj>*) - pass a pointer by value

A copy of the pointer is made. Internally, changes to the pointer itself aren't reflected on the outside. Changes to the vector it points to are. So the effect is different from the option before - if you want to make changes that aren't reflected on the outside, you need a copy anyways.

func(/*const*/ vector<obj>&) - pass by reference

If not const, changes are reflected on the outside. Again, different semantics - if you're modifying the object, changes will be reflected on the outside. If you don't want that (changes reflected on the outside), you need a copy anyway.

The decision between the three isn't trivial.

The second one is closer to what you'd do in C, so I'd avoid it if I could (not needed + you can achieve the same effect with pass-by-reference + no naked pointers).

If you want to modify the object inside the function and have the changes reflected on the outside, use pass by non-const reference. This couldn't be achieved by pass-by-value anyway.

If you don't plan on modifying the object, use pass by const reference. This guarantees no copy is made, and that you're not modifying the object.

If you want to modify the object but not have the changes reflected on the outside, use pass-by-value. In situations where changes wouldn't be reflected on the outside, a copy is avoided (i.e. when you pass a temporary) and a move is preferred. In situations where they would, you'd need a copy of the original object anyway.

Community
  • 1
  • 1
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • +1 Great answer, way better than mine. I wasn't very much aware of this move condition. – Natan Streppel Sep 24 '13 at 23:25
  • Thank you so much for the detailed answer. What I want is actually your last paragraph, modify the object inside but not outside. But I cannot afford a copy of the vector, it's simply too large. Could you explain more on the `move semantic`? How is it used and do I have to write explicitly I want move but not copy? – Logan Yang Sep 25 '13 at 00:16
  • @LoganYang how could you modify the *same* object without having the changes on the outside. You need a copy, right? – Luchian Grigore Sep 25 '13 at 08:42
  • Then changes on the outside is fine, I just need to reset them afterwards. My priority is to avoid copying the huge vector – Logan Yang Sep 25 '13 at 08:53
  • @LuchianGrigore Sorry I'm still not clear about what you wrote under **pass by value**. Is it true that I compile with `-std=c++11` and pass the vector by value into the function, it does not copy but really does move? Is there a copy or not? – Logan Yang Sep 26 '13 at 08:40
  • @LoganYang in situations where it matters, it's a move. (when you pass a temp). Best way to find out is profile. If performance is an issue, profile. You should guide yourself following the last part of the answer. What do you want to achieve? Do you plan on modifying the object inside, and if so, do you want the changes to be reflected on the outside? – Luchian Grigore Sep 26 '13 at 08:53
  • @LuchianGrigore I'm modifying the object inside just to achieve the things I want with the function. It's not important it's modified or not on the outside. If modified, I just need to reset the objects to the former state, not a big deal, just some more time. Yes I'm gonna profile and see if the memory is overused. Thanks! – Logan Yang Sep 27 '13 at 00:36
  • @LoganYang that's what I don't really get. How do you simply "reset" some of the objects you modify? That means you somehow retain the original state, which means you already have a copy somewhere, right? – Luchian Grigore Sep 27 '13 at 06:15
  • @LuchianGrigore By that I meant if I chose to pass by reference and completely get modified from the outside, that's fine. "reset" is just to set all modified value to zero, which is the original state, don't need to remember that somewhere. :) – Logan Yang Sep 27 '13 at 07:22
  • @LoganYang then why are you passing it as a parameter to start off with? To me, it seems your signature could just be `func()` and you can create a local vector inside. – Luchian Grigore Sep 27 '13 at 07:38