The following illustrates the basic usagle of vectors.

// array-ex1.cpp (click here to download)

#include <iostream> #include <vector> using namespace std; int main() { vector<int> v(10,0); // initialise to 10 copies of 0 int s = v.size(); cout << "size of v is " << s << endl; for (int n=0; n<s; n++) { v[n] = n; } for (int n=0; n<s; n++) { cout << "v[" << n << "] == " << v[n] << endl; } // the following code is very bad /* for (int n=0; n<20; n++) { cout << "v[" << n << "] == " << v[n] << endl; } */ // the following code is very VERY bad /* for (int n=0; n<20; n++) { v[n] = n; } */ return 0; }

Note the code `vector<int> v(10,0);` to declare
`v` and initialise it to 10 copies of 0. Without the
`(10,0)` the vector would be initially empty.

For reasons we will see shortly, passing vectors to functions should be done using call-by-reference. (At least almost always!) Functions frequently change vectors as side effects. Here is an example with a void function operating on an vector.

// array-ex2.cpp (click here to download)

#include <iostream> #include <vector> using namespace std; void printvector(vector<double>& v) { int s = v.size(); for (int n=0; n<s; n++) { cout << v[n] << " "; } cout << endl; } /* assigns v[n]=1 v[n+1]=2 v[n+2]=3 where n==index */ void set123(vector<double>& v, int index) { v[index] = 1.0; v[index+1] = 2.0; v[index+2] = 3.0; } int main() { vector<double> v(10,0); // initialise to 10 copies of 0 int s = v.size(); cout << "size of v is " << s << endl; for (int n=0; n<s; n++) { v[n] = n; // convert n to double } printvector(v); set123(v,5); printvector(v); set123(v,13); // bad but how to fix it? printvector(v); return 0; }

The code contains a bad line `set123(v,13);`.
Suppose you didn't know that the size of this vector was 10.
Then how should the code be fixed? There are many choices here.

- One possibility is to change
`main`: use`v.size()`to get the size and compare 13 with this size. - The other is to change
`set123`.

There are three problems with changing `main`:
first it takes computer time to to get the size and compare;
second there seems to be no way of checking what values for

are valid (and surely it is the job of the function
`index``set123` to know what are valid values for `index`?);
thirdly, if `set123` is used elsewhere we have the same problem
all over again. So it is better to change `set123`. This
was my solution:

// array-ex3.cpp (click here to download)

#include <iostream> #include <vector> using namespace std; void printvector(vector<double>& v) { int s = v.size(); for (int n=0; n<s; n++) { cout << v[n] << " "; } cout << endl; } /* assigns v[n]=1 v[n+1]=2 v[n+2]=3 where n==index Here, index is checked and must be in the range 0 .. v.size()-3 If index is out of range then nothing is done and a warning message is sent to cerr. */ void set123(vector<double>& v, int index) { if (index<0 || index>v.size()-3) { cerr << endl << "WARNING: in function set123, input value " << index << " is out of range!" <<endl; return; // quit function doing nothing } v[index] = 1.0; v[index+1] = 2.0; v[index+2] = 3.0; } int main() { vector<double> v(10,0); // initialise to 10 copies of 0 int s = v.size(); cout << "size of v is " << s << endl; for (int n=0; n<s; n++) { v[n] = n; // convert n to double } printvector(v); set123(v,0); printvector(v); set123(v,13); printvector(v); return 0; }

Note that I had other choices to make: what to do if a problem occurs.
I chose to make a loud warning to the error console `cerr`.

Vectors of bool are very useful. The following needs little additional explanation.

// eratosthenes.cpp (click here to download)

#include <iostream> #include <vector> using namespace std; // Sieve of Eratosthenes /* sets the input vector isprime[] so that it has size nentries and isprime[n]==true iff n is prime for all n < nentries */ void setsieve( vector<bool>& isprime, int nentries) { // resets isprime to a vector of size nentries, all true isprime.resize(nentries,true); isprime[0] = isprime[1] = false; int trialn = 2; for (int trialn = 2; trialn < nentries; trialn++) { if (isprime[trialn]) { int multiple = trialn + trialn; while (multiple < nentries) { isprime[multiple] = false; multiple = multiple + trialn; } } } } int main() { vector<bool> isprime; int nentries; cout << "Number of entries? " << endl; cin >> nentries; setsieve(isprime, nentries); for (int i=0; i<nentries; i++) { if (isprime[i]) cout << i << " "; } cout << endl; return 0; }

Interestingly, this gives a table of all primes less than 1000000000 in very reasonable time. To go much beyond this will require care with int overflow.

Finally, why do I insist vector arguments in functions should be call by reference? Find out with this.

// arrayrefs.cpp (click here to download)

// this program illustrates why call-by-reference is neccessary // when passing arrays (vectors) as arguments to functions #include <iostream> #include <vector> using namespace std; /* This function returns the ith value in the vector v, i.e. it is equivalent to v[i] This is a trivial operation that you'd not normally put in a function, but you can easily imagine that more complicated functions that read several values from v might be useful. Here we (incorrectly) use call-by-value for v */ double badf(vector<double> v, int i) { return v[i]; } /* This function returns the ith value in the vector v, i.e. it is equivalent to v[i]. Here we (correctly) use call-by-reference for v. */ double goodf(vector<double>& v, int i) { return v[i]; } int main() { // size of the vector in this example int vsize = 100000; // set the next two variables as you want! bool do_badf = true; bool do_goodf = true; // create a vector of doubles, initially empty vector<double> myvector; for (int i=0; i<vsize; i++) { myvector.push_back(i); } // now calculate the sum of the values badf(myvector,-) in myvector if (do_badf) { double runningsum = 0.0; for (int i=0; i<vsize; i++) { runningsum = runningsum + badf(myvector,i); } cout << runningsum << endl; } // now calculate the sum of the values goodf(myvector,-) in myvector if (do_goodf) { double runningsum = 0.0; for (int i=0; i<vsize; i++) { runningsum = runningsum + goodf(myvector,i); } cout << runningsum << endl; } // return success as usual return 0; }

In this example program the functions badf and goodf do something
quite trivial, and could be replaced by a single expression
`v[i]`. But it's not difficult to imagine that even only slightly
more complicated functions would be useful when written as a
function in a similar way.