Why static arrays can't be passed by value but vectors can?

As far as I know, C++ doesn't allow static arrays being passed by value, since you don't even need to add the & in the parameter list to end up (internally) with a pointer to the first element to the array.
I understand that it's not desirable to pass arrays by value because of the memory issues.
But then, why does C++ allow a parameter like
 
vector<type> parameterName


Thanks.
Last edited on
A vector is a small class that looks something like this:

1
2
3
4
5
6
7
8
9
template <typename T>
struct vector
{
  T*     data;
  size_t capacity;
  size_t used;

  // methods...
};

All the stuff in the vector/array/data is actually on the heap, not the stack. Thus, the cost of passing a vector around is very little.

Hope this helps.
I thought that if you pass a vector to a function by value, then the copy-constructor of the vector will be invoked in order to create the temporary version that will be used in the function. The copy constructor will perform a deep copy (making a copy of all of the memory pointed to by "data"), which means that the cost of passing a vector by value can in fact be significant. Is that not the case?
Oh, so let me see if I got it right:

Let's say I have a struct like this:
1
2
3
4
5
6
struct typeA
{
	long first;
	string second
	double third;
};


- If I declare
 
typeA myArray[100];


Then myArray is stored in the stack, consuming sizeof(typeA)*100 bytes of garbage data.
Whenever I pass this array as a parameter, I'll always be passing a pointer to the first of the first element in the stack. So the pointer goes from stack to stack.

- But if I declare
 
vector<typeA> myVector (4, 100);


Then myVector is actually a vector struct (like the one you showed) stored in the stack, and it contains a pointer to the first element of an array of 4*sizeof(int) bytes stored in the heap, containing the actual data. So pointer goes from stack to heap.
Whenever I pass this vector as a parameter, if I add it to the parameter list like this
 
vector<typeA> parameterVector

the function gets a copy of the struct stored in the stack (containing pointers to the actual elements).
But if I do it like this:
 
vector<typeA> &parameterVector

the function gets a pointer to the struct stored in the stack, so I now have a pointer stored in the stack, referencing a struct also stored in the stack, that contains pointers to elements stored in the heap.

Is this correct?
Edit: I just read Norm Gunderson's reply. If that's true, then I got the whole thing wrong :P
Thanks!
Last edited on
Hi,

Edit: anarelle I didn't see your post while I was typing my reply.

This might seem a bit complicated and way over the top, but here goes.

C++ also has move semantics, which use rvalue references.

Basically, when one returns a container from a function, the compiler "moves" the container being returned. The basic concept of that is: The memory address of the old value now belongs to the new variable. The old variable may or may not still exist.

The container must have move semantics enabled, which means it must have a move constructor. I am fairly sure that all the STL containers have them.

The move constructor uses rvlaues denoted by 2 & after the variable name (as in variable&& ) . There are different types of rvalues, in the case of returning from a function, it is an xvalue. The 'x' means "expiring" which is easy to remember because the returned value is going out of scope.

When passing a container to a function, then it is as Norm Gunderson, unless (as I understand it) the argument is a call to std::move (not sure why one would do that), so it's best to pass containers by reference. So this includes std::string and any class that you might invent yourself.

I hope my simplistic explanation has of been some help. The topic is not simple IMO, so it is probably best to read up about it.


http://en.cppreference.com/w/cpp/language/move_constructor
http://www.stroustrup.com/terminology.pdf
Last edited on
Arrays was inherited from C. If arrays was added to C++ today without having to care about backward compatibility I'm sure they would have allowed them to be passed by value and copied the same way as any other object.

In C++11 the array class template was added to C++. It's pretty much just a static array wrapped in a class to allow it to be copied like other containers.

http://www.cplusplus.com/reference/array/array/
But if I do it like this:

vector<typeA> &parameterVector


Better to pass by reference:

vector<typeA> parameterVector&

Which is almost the same as what you had, but better. A reference must refer to an actual object, whereas a pointer can be made to point at anything - this is bad, and is why we try to avoid naked pointers.

Note one can't return a reference from a function - it goes out of scope. But just return the object so the move thing happens, or make a function parameter a reference, so the value is changed in the outer scope.

One problem is that it is not possible to have a container of references, but there is std::reference_wrapper which allows one to do the same thing.

There is also smart pointers, which are used to do RAII - this is very good practice. It avoids having new and delete - they have there own problems. Smart pointers were designed to avoid memory leaking.

http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
http://www.cplusplus.com/reference/functional/reference_wrapper/
http://www.cplusplus.com/reference/memory/unique_ptr/
Last edited on
The correct syntax is vector<typeA> &parameterVector

> Note one can't return a reference from a function - it goes out of scope
you shouldn't return a reference to a local variable.
Returning a reference may be perfectly fine and desirable. By instance
1
2
3
4
5
6
7
8
9
ostream& operator<<(ostream &out, const Foo &bar){
   //...
   return out;
}

Foo& operator=(Foo bar){
   //...
   return *this;
}



> Thus, the cost of passing a vector around is very little.
the cost of moving the vector may be very little

> the copy constructor will perform a deep copy which means that
> the cost of passing a vector by value can in fact be significant.
correct
Last edited on
Topic archived. No new replies allowed.