vector as an argument

Pages: 123
i know c++ can pass argument by value and by reference and arrays are passed only by reference to a function. what about vectors? passed by ref or val or both?
closed account (oz10RXSz)
Both. But:

1. From the performance point of view you should never pass them by val.
2. From the correctness/safety point of view you should never pass them by ref.
The choice is yours. :D
Last edited on
2. From the correctness/safety point of view you should never pass them by ref.

There's nothing incorrect or unsafe about passing it by reference.
closed account (oz10RXSz)
There is. There are mainly two potential problems that you must think of before passing it by ref:
1. The receiver modifies the vector - might break the caller.
2. The receiver stores the reference to the vector and the caller modifies the vector afterwards - might break the receiver.

The first one can be mitgated by using const ref. But then if the receiver wants to do something with this vector, e.g. store it somewhere, it is forced to make a copy. There is no protection against 2., except making a defensive copy, but this is just as passing it by val. So, in both cases if you want security and lack of strong coupling you are forced to sacrifice performance.

In small programs this is not an issue. In large programs this yields often hard to find bugs - the types of bugs that you sit for a week in front of the debugger and you try to find out why the given variable changed "magically", what did this and why it happens randomly.

Another solution is simply using immutable vector, but there are none in C++, so you must roll your own. However, I haven't seen anyone doing this. Switching to language with a better standard library is easier.
Last edited on
1. if it modifies the vector, that's not a "problem", but rather the purpose or a wanted by-product of the function.
If it doesn't modify the vector, the reference should be const. If it needs a copy, it should make a copy. Simple.
The copy would occur either way when passing by value, whether it's necessary or not.

2. The receiver can't just go and store a reference to an object without knowing anything about its lifetime.
If it does know the passed object will outlive its own lifetime, there is no problem.

In small programs this is not an issue. In large programs this yields often hard to find bugs - the types of bugs that you sit for a week in front of the debugger and you try to find out why the given variable changed "magically", what did this and why it happens randomly.

That's not a problem caused by references, but by poor design, such as no clear object ownership.
Last edited on
I second both Athar's posts.
closed account (oz10RXSz)

That's not a problem caused by references, but by poor design, such as no clear object ownership


You see, "in nature" there is no such thing like object ownership. Objects just are. Object ownership is an imperfect solution created to overcome problems with references to mutable data.

And this is why I have written that in small programs this is not a problem. In small programs it is easy to keep ownership and object lifetime clean. But in large programs, written by many people at different times, keeping clear ownership is difficult. Besides, for some kinds of objects having an owner is a limitation, causing additional complexity. E.g. when you optimize things, you cannot just take a frequently called function and cache its results, without analyzing the whole program (not the function implementation itself). You could cause a disaster by such an optimization.

Last edited on
guys dont get me wrong
this is im sayin...

1
2
int a[10]
function(a)

in above code "a" passed by ref .ok?
according to this :
http://www.cplusplus.com/doc/tutorial/arrays/
In C++ it is not possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and more efficient operation.


now i wanna know is it possible to pass vector by value???(i think it's not cuz it's a block of memory)
if we have
vector<int> b
function(b)
then we pass b by ref/is that right?
(i am trying to write huffman coding using vectors and i do want to modify it in reciever function.)

Both. But:

1. From the performance point of view you should never pass them by val.
2. From the correctness/safety point of view you should never pass them by ref.
The choice is yours. :D

are you sure xoreaxeax ?
Last edited on
closed account (oz10RXSz)
No.

By val:
 
void function(vector<int> v)


By ref:
 
void function(const vector<int>& v)


The vector has an overloaded copy-constructor and it would copy the data by itself when passed by val. But if you want to modify the passed arguments, you should pass by val. Functions modifying their arguments are poor design.
Last edited on
@sourena: your function signature should look like this:

void function(std::vector<int>& vec);

Passing by reference should mean you're going to modify the object. Passing by const reference should mean you just need to read the object. Passing by value should mean you need to copy the object. Just keep these "rules" in mind.
closed account (oz10RXSz)

Passing by reference should mean you're going to modify the object


Yes, but functions modifying their arguments are considered antipattern by many.
The problem is you don't see such modifications in the client code:

1
2
3
4
5
6
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
int x = function(vec);
// how can you know vector still contains 1, 2 and 3? 


So, use it sparsely, only when really needed.

Last edited on
thx filipe...i got it.
thx all guys.
+1 Athar

1
2
3
void func(const std::vec<int>& list); // to make the list available

void func(std::vec<int>& list); // to process/populate the list 


Making a copy and then returning a copy doesn't make a lot of sense for a processing function:

 
std::vector<int> func(std::vec<int> list); // not very efficient for a list processing function 


Making a copy for a function that merely needs to use the list can make sense but not very often:


 
void func(std::vec<int> list); // Can be useful if a copy will be required 

closed account (oz10RXSz)
Rather than:
 
void func(std::vec<int>& list); // to process/populate the list  


you should use:

 
std::vector<int> func();  // creates a new list  


Both have the same performance but the intent is much more clear in the second one. Objects should be created in their final state immediately as often as possible. The return value is for returnig data from functions, the arguments are for passing data to functions.


Making a copy and then returning a copy doesn't make a lot of sense for a processing function


This is true only in such languages like C++, where making a copy of the list is very costly i.e. O(n). In many languages making a copy of the list is an O(1) operation and then this pattern makes perfectly sense.
Last edited on
Sure, this is fine if you don't need to process/add to/remove from a pre-existing list.
std::vector<int> func(); // creates a new list
xoreaxeax wrote:
This is true only in such languages like C++, where making a copy of the list is very costly i.e. O(n). In many languages making a copy of the list is an O(1) operation and then this pattern makes perfectly sense.


Out of curiosity, which languages can copy n items in O(1) time?
Last edited on
I'm beginning to think xoreaxeax doesn't really know what he is talking about...

Functions modifying their arguments are poor design.


No. That's like saying "Functions returning values is poor design because I can't automatically know what the value will be."

Anyway, +1 to Athar.
closed account (oz10RXSz)

That's like saying "Functions returning values is poor design because I can't automatically know what the value will be."


Tell it your maths teacher. :D

Functions assign a return value to their arguments. So:
1. arguments = input
2. return value = output

Just because you can use arguments for output in C/C++ functions (so they are procedures returning a value, but not functions in mathematical sense) does not mean you should use it whenever posssible. Ok, actually sometimes there is no other solution, but you should not do it as a default. I find it bad style.


Out of curiosity, which languages can copy n items in O(1) time?


All that use immutable lists/vectors/maps in their standard libraries. Scala, Haskell, OCaml, ML, LISP. You just don't need to ever make copy - you pass reference where in C/C++ you would have to make a copy.
Tell it your maths teacher. :D


Irrelevant. This is about C++.

does not mean you should use it whenever posssible.


Agreed. When did we state you should always use it?

All that use immutable lists/vectors/maps in their standard libraries. Scala, Haskell, OCaml, ML, LISP. You just don't need to ever make copy - you pass reference where in C/C++ you would have to make a copy.


Then you aren't copying n items, you are basically making a pointer/reference to it. A C++ list is a mutable list. If you want an immutable list, you just pass it by const reference.
closed account (oz10RXSz)
Then you aren't copying n items, you are basically making a pointer/reference to it


Semantically they are the same if only the data structure is immutable. The compiler is free to choose, whether it makes a copy or pass a reference (making a copy can sometimes be much more efficient, in case of NUMA architectures). There is no need to have that distinction in the language.


If you want an immutable list, you just pass it by const reference


Immutable != const. Const does not protect from the problem of modifying the list by the caller afterwards. So does not guarantee immutability, even the shallow one. It is much weaker. Thus in C++ pass by ref has different semantics than pass by val, regardless it is const or not. If I'm gonna do something with the received vector afterwards, I need to either make a copy (inefficient) or prey that someone doesn't screw my code by modifying the caller code (which may be totally different module, written by a different person).

Pass by ref makes my code easily breakable by changes in other places of code, not directly coupled with my code. So, pass by ref (or pass by pointer) introduces hidded code dependencies that are difficult to maintain in a code base of 1 million SLOC. It breaks encapsulation and simply doesn't scale up. This is why most modern languages use immutable strings as a basic data structure for text and not mutable ones like in STL.

BTW: Passing by const ref forces me to do costly O(n) copy whenever I need to change something in the vector/list. If this was an immutable vector I still would be able to work on it efficiently - adding or removing items can be still O(1) or O(log n) on persistent structures (there are no in STL or Boost).
Last edited on
Pages: 123