Re: vector.clear() and vector copying
On 23 Mar, 00:44, "Jess" <w...@hotmail.com> wrote:
Thanks for all the replies and sorry for not being too specific, here
is my code. :)
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
vector<int> v1;
vector<int> v2;
vector<string> v3;
v1.push_back(1);
v1.push_back(2);
v2.push_back(3);
v3.push_back("a");
cout << v1.size() << endl; //output size is indeed 2
cout << v2.size() << endl; //output size is indeed 1
cout << v3.size() << endl; //output size is indeed 1
v1.clear(); //clear v1
cout << v1.size() << endl; //v1's size is indeed 0
cout << v1[0] << endl; //output is 1, garbbage?
The behaviour of the above statement, specifically the expression
v1[0] which attempts to access the first element of a vector with no
elements, is undefined. Any output is as valid or invalid as any other
output, and any other behaviour (e.g. a crash) is as valid or invalid
as outputting something.
v3.clear();
cout << v3.size() << endl; //size is indeed 0
cout << v3[0] << endl; //null string on one machine, and
"Segmentation fault" on another
As before, the behaviour of v3[0] is undefined. Outputting a null
string is just as vaild or invalid as a segmentation fault.
//vector copying
v1.push_back(1); //put back the values again
v1.push_back(2);
v1 = v2; //copy v2 to v1
cout << v1.size() << endl; //v1's size has been decreased to 1
return 0;
}
If I used vector.at() as suggested by Erik for v1.at(0), then I got
"Abort".
You are getting undefined behaviour with v1[0] because you are trying
to access an element that doesn't exist. v1[n] has undefined behaviour
for any n >= the number of elements in the vector (>= rather than >
because indices start at 0). If you are going to access elements of a
vector using v1[n] it is your responsibility as the programmer to
ensure that n is a valid index, i.e. n < the number of elements in the
vector.
However, vector being a sensibly designed class, a vector object knows
how many elements it has. The at() member function provides a
different way of accessing elements. When you do v1.at(n), inside the
at function, the vector checks for itself whether n is a vaild index.
If so, it returns you the element just like v1[n], but this time if n
is not a valid index, at throws an exception (of type
std::out_of_range). The important distinction is that this behaviour
is well defined and reliable, unlike the behaviour of v1[n] for
invalid n. You saw an abort because your program did not catch the
exception so it terminated in the same way it would for any uncaught
exception.
So, is vector.at() a much better way to access vector's
content than indices?
Not necessarily. The undefined behaviour in your program was due to
bugs that could have been avoided (avoided easily now you know how
element access works for vectors). A program like yours controls the
size of the vector and controls the indices used (as opposed to, for
example, asking a user to type in sizes and indices) so an out of
range index will only ever be a programmer error. The solution is to
fix the error. Having said that, while you are learning to use
vectors, and presumably writing programs with them that are a little
more complex than your demo program here, you may find it useful to
use at() quite liberally to help you identify bugs. As you get the
hang of it, you will quickly indentify situations where you can be
confident enough in the code that you don't need the extra protection
of at().
Much of the time I use [] to access vector elements it is in a loop
like
vector<int> v(42);
for (vector<int>::size_type index = 0; index < v.size(); ++index)
{
// Do something with v[index].
}
Because of the way the loop is written, I know that index must be
valid for every iteration [*] so at() doesn't offer me any advantage.
But more often I use iterators rather than indices to access elements
anyway.
[*] Assuming I don't do anything inside the loop that modifies the
size of the vector, but that's generally something to be very careful
with anyway because it makes the loop harder to get correct.
Gavin Deane