• (3 Pages)
  • +
  • 1
  • 2
  • 3

C++ Vector Tutorial Constructors, accessing elements, and getting internal state informati Rate Topic: ***** 10 Votes

#1 jjhaag  Icon User is offline

  • me editor am smartastic
  • member icon

Reputation: 44
  • View blog
  • Posts: 1,789
  • Joined: 18-September 07

Posted 19 September 2007 - 10:26 PM

*
POPULAR

Introduction
--------------

In C++, vectors are one type of dynamically-allocated container from the standard template library (STL). They are capable of storing multiple elements of any defined datatype, and do so in a contiguous block of memory. Unlike raw arrays, vectors are access-safe as long as you use the builtin access methods associated with them. Thus, overrunning the end of a vector will throw an exception rather than crashing the program. For quickly writing access-safe code that requires very little in the way of programmer intervention for memory management, they are hard to beat. There are reasons to use other containers from the standard template library (such as lists or double-ended queues), but vectors are generally the first choice of most programmers for their versatility and speed.

In this tutorial, Iím aiming to pass along some of what Iíve learned over the years. However, I am a self-taught C++ coder, and most of my learning was through trial-and-error. This means that there may be errors that I havenít picked up yet, so please let me know if there are any problems. Most of the code Iíve presented is complete with all the includes and such, so readers can copy+paste it straight into an IDE to run themselves and play around with.

Iíve also realized as Iíve been writing that this thing has gotten pretty long, so itís been broken up into a couple of sub-tutorials (second one, hopefully, to follow).

Happy coding,

-jjh


PART I:

Vector Constructors

The available constructors for a vector are given by:

vector<int> testVector;
vector<long> testVector(10);
vector<float> testVector(5,1.0);



The first syntax declares an empty vector capable of storing the integer datatype. The second declares a vector with storage space for 10 long integers, each of which is intialized to the default value for the type. The final line declares a vector with storage for 5 floats, and initializes each of their values to 1.0. Any valid type can be used for any of the constructors.

There is also a copy constructor for the std::vector class. The following code creates a vectors of integers with 10 copies of the number 5, and duplicates the vector into a new one using the copy constructor:

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	vector<int> vectorOne(10,5);
	
	vector<int> vectorTwo(vectorOne);
	
	return EXIT_SUCCESS;
}



Of course, there is really no way of knowing what the program does or whether it has performed as expected, since as yet we know of no way to get at the information stored in the vector. So, on to...


Acessing Elements of a Vector
There are a number of ways to access the elements of a vector. For the moment, I will focus on two of them, one safe and one unsafe. And as a reminder, C++ vectors (and other STL containers), like raw C/C++ arrays, are accessed with indices starting at zero. This means that the first element is at position 0 in the vector, and the last element is at position (number of elements)-1.

The vector class contains a member function at() for accessing individual elements of a vector. This is the safe way of accessing elements, since attempting to access an element beyond the valid range will cause an exception to be thrown. However, the raw data stored in the vector can still be accessed using the usual [] operator, just like in a raw array. Unfortunately, just like with a raw array of data, overrunning the end of the vector using the [] operator can cause weird and unexpected things to occur, such as program crashes or unexpected results. It may also return garbage data that follows the meaningful data of the vector, which has the potential to be disastrous if it is used in subsequent operations. The following two code snippets demonstrate each of these access methods:

Safe access version
#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	/*  Initialize vector of 10 copies of the integer 5 */
	vector<int> vectorOne(10,5);
	
	/*  run through the vector and display each element, if possible */
	for (long index=0; index<20; ++index) {
		try {
			cout << "Element " << index << ": " << vectorOne.at(index) << endl;
		}
		catch (exception& e) {
			cout << "Element " << index << ": index exceeds vector dimensions." << endl;
		}
	}
	
	return EXIT_SUCCESS;
}




Unsafe access version
#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	/*  Initialize vector of 10 copies of the integer 5 */
	vector<int> vectorOne(10,5);
	
	/*  run through the vector and display each element, if possible */
	for (int index=0; index<20; ++index) {
		cout << vectorOne[index] << endl;
	}
	
	return EXIT_SUCCESS;
}



The first version prints out the 10 copies of the number 5 which were stored in the vector, then "Element DD: element DD exceeds vector dimensions." 10 times. The second version manages to print out, on my machine at least, 10 copies of the number 5 followed by a bunch of garbage integers. The garbage is all of the meaningless stuff found beyond the actual 10 numbers that we initialized the vector to contain. Of course, if we remove the try-catch statement from the first version of the code, the program will exit, with (on Windows) a message to contact the application's support team. This is bad, and just points out how important it is to implement proper exception-handling. If what you're writing is for your own personal use, you ARE the support team, so you'll need to figure it out. If you're writing for someone else, or as part of your job, you may be getting and email, a call, or, if it happens frequently enough with your software, a pink slip.


Getting Internal State Information About a Vector
The vector container has a number of member functions that give the programmer information about its internal state. One of the most important of these functions, especially in light of the above example, is the member size(). As the name implies, size() returns the number of elements in the vector. This function can be especially useful in loops that access the elements of a vector, such as the one presented above. In simple cases without insertions or deletions of elements, it can be used to forego the exception handling blocks (though I know some programmers might go ballistic over that last statement).

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	/*  Initialize vector of 10 copies of the integer 5 */
	vector<int> vectorOne(10,5);
	
	/*  Display size of vector */
	cout << "Size of vector is " << vectorOne.size() << " elements." << endl;
	
	/*  run through the vector and display each element, using size() to determine index boundary */
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << "Element " << index << ": " << vectorOne.at(index) << endl;
	}
	
	return EXIT_SUCCESS;
}




There are two other member functions that are closely related to size(). So closely related, in fact, that they are frequently confused with size() by novices and experts alike. These functions are capacity() and max_size().

The function capacity() returns the number of elements that the vector can hold before more space is allocated. It is very important to remember here that, unlike raw arrays, most of the memory management for vectors is performed silently during construction or manipulation of the container. When a vector is declared or initialized to contain a specified number of elements, the program may allocate more space than is currently needed, under the assumption that, because you are using dynamically allocated storage, the storage requirements may change over time. If extra space is allocated, it allows the program to add additional elements without an allocation step. This prevents the performance hit that would otherwise be expected if new space were allocated for every new element added. Once the vector contains the same number of elements as its capacity, new space is allocated when a new element is inserted. But again, to maximize performance, when a reallocation occurs, more space is allocated than is currently needed.

The function max_size() should not be confused in any way with the function capacity(). max_size() returns the maximum number of elements that the container can hold. Notice that there is no qualifier about memory allocation here. max_size() is determined by the system, the compiler, and the computerís architecture, and refers to memory address space limitations on a particular machine.

Closely related to the size() and capacity() functions are resize() and reserve(). While size() and capacity() allow the programmer to get information about the container, resize() and reserve() allow the programmer to set these values.

resize() changes the actual number of elements in a vector. The syntax is given by:

void resize(size_type num)
void resize(size_type num, const TYPE& val=TYPE())



resize() is most often used to increase the number of elements in a vector, in which case the first will initialize these new elements to their default value, whereas the second will intialize all of the new elements to val. The resize() function can also be used to decrease the number of elements, which results in the truncation of the last (num-vectorName.size()) elements. The following code initializes a vector containing 10 copies of the number 5, then truncates the last 3 elements by resizing the vector to contain only 7 elements. Play around with the line vectorOne.resize(7) to see the effect of the resize function.

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	/*  Initialize vector of 10 copies of the integer 5 */
	vector<int> vectorOne(10,5);
	
	/*  Display size of vector */
	cout << "Size of vector is " << vectorOne.size() << " elements." << endl;
	
	/*  run through the vector and display each element, using size() to determine index boundary */
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << "Element " << index << ": " << vectorOne.at(index) << endl;
	}
	
	/*  Change size of vector - element removal */
	vectorOne.resize(7);
	
	/*  Display size of vector */
	cout << "Size of vector is " << vectorOne.size() << " elements." << endl;
	
	/*  run through the vector and display each element, using size() to determine index boundary */
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << "Element " << index << ": " << vectorOne.at(index) << endl;
	}
	
	return EXIT_SUCCESS;
}



reserve() is to capacity() as resize() is to size(). It causes a reallocation of memory so that the vector will hold (at minimum) the specified number of elements. In programs that have a lot of insertions into vectors, using reserve wisely can help boost performance substantially, especially if the vectors in question are quite large. The following code brings together size(), capacity(), resize() and reserve() to show some simple vector allocation operations.

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char** argv) {
	
	//  initialize vector of integers with 20 elements
	vector<int> vectorOne(10);
	
	
	
	
	//  display size and capacity of vector
	cout << "Size of vectorOne is: " << vectorOne.size() << " elements." << endl;
	cout << "Capacity of vectorOne is: " << vectorOne.capacity() << " elements." << endl;
	
	//  put some random data into the vector using at()
	for (long index=0; index<(long)vectorOne.size(); ++index) vectorOne.at(index)=rand();
	
	//  display vector contents
	cout << "vectorOne contains the following elements:" << endl;
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << vectorOne.at(index) << " ";
	}
	cout << endl << endl;
	
	
	//  reserve more space for the vector and repeat
	cout << "Using reserve to reallocate vectorOne with enough storage for 40 elements."  << endl;
	
	vectorOne.reserve(40);
	
	//  display size and capacity of vector
	cout << "Size of vectorOne is: " << vectorOne.size() << " elements." << endl;
	cout << "Capacity of vectorOne is: " << vectorOne.capacity() << " elements." << endl;
	
	//  put some random data into the vector using at()
	for (long index=0; index<(long)vectorOne.size(); ++index) vectorOne.at(index)=rand();
	
	//  display vector contents
	cout << "vectorOne contains the following elements:" << endl;
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << vectorOne.at(index) << " ";
	}
	cout << endl << endl;
	
	
	//  add elements to vector using resize
	cout << "Using resize to increase size of vector to 15 elements, with new elements set to 0." << endl;
	vectorOne.resize(15,(int)0);

	//  display size and capacity of vector
	cout << "Size of vectorOne is: " << vectorOne.size() << " elements." << endl;
	cout << "Capacity of vectorOne is: " << vectorOne.capacity() << " elements." << endl;
	
	//  put some random data into the vector using at()
	for (long index=0; index<(long)vectorOne.size(); ++index) vectorOne.at(index)=rand();
	
	//  display vector contents
	cout << "vectorOne contains the following elements:" << endl;
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << vectorOne.at(index) << " ";
	}
	cout << endl << endl;
	
	
	//  remove elements from vector using resize
	cout << "Using resize to decrease size of vector to 5 elements." << endl;
	vectorOne.resize(5);
	
	//  display size and capacity of vector
	cout << "Size of vectorOne is: " << vectorOne.size() << " elements." << endl;
	cout << "Capacity of vectorOne is: " << vectorOne.capacity() << " elements." << endl;
	
	//  put some random data into the vector using at()
	for (long index=0; index<(long)vectorOne.size(); ++index) vectorOne.at(index)=rand();
	
	//  display vector contents
	cout << "vectorOne contains the following elements:" << endl;
	for (long index=0; index<(long)vectorOne.size(); ++index) {
		cout << vectorOne.at(index) << " ";
	}
	cout << endl << endl;

	
	return EXIT_SUCCESS;
}



The output from the above code on my machine is:

size() of vectorOne is: 10 elements.
capacity() of vectorOne is: 10 elements.
vectorOne contains the following elements:
41 18467 6334 26500 19169 15724 11478 29358 26962 24464 

Using reserve() to reallocate vectorOne with enough storage for 40 elements.
New size() of vectorOne is: 10 elements.
New capacity() of vectorOne is: 40 elements.
vectorOne contains the following elements:
41 18467 6334 26500 19169 15724 11478 29358 26962 24464 

Using resize() to increase size of vector to 15 elements, with new elements set to 0.
New size() of vectorOne is: 15 elements.
New capacity() of vectorOne is: 40 elements.
vectorOne contains the following elements:
41 18467 6334 26500 19169 15724 11478 29358 26962 24464 0 0 0 0 0 

Using resize() to decrease size of vector to 5 elements.
New size() of vectorOne is: 5 elements.
New capacity() of vectorOne is: 40 elements.
vectorOne contains the following elements:
41 18467 6334 26500 19169 



This concludes Part I. In the next part, I will move on to methods associated with adding or removing elements of a vector.

This post has been edited by jjhaag: 25 September 2007 - 09:13 PM


Is This A Good Question/Topic? 21
  • +

Replies To: C++ Vector Tutorial

#2 93FFF  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 19-November 07

Posted 10 December 2007 - 01:24 PM

This was put together very well. Thank you so much! I have a much better understanding on Vectors.
Was This Post Helpful? 0
  • +
  • -

#3 ProfBeginner  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 24-October 08

Posted 24 October 2008 - 02:55 AM

Thank you for explaining Vectors. I am beginning to understand them. :D
Was This Post Helpful? 0
  • +
  • -

#4 NoviceC++Programmer  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 28-December 08

Posted 04 January 2009 - 08:05 AM

Thanks that is too good........ where is the next part??

please reply soon.

:D
Was This Post Helpful? 0
  • +
  • -

#5 Haradan  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 2
  • Joined: 09-February 09

Posted 09 February 2009 - 06:02 PM

Really brilliant tutorial but where's the rest of it?! You didn't even reserve any extra posts. It's been over a year so I guess it's just not happening now. :(
Was This Post Helpful? 0
  • +
  • -

#6 shabtai  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 19-January 09

Posted 18 February 2009 - 04:00 PM

View PostHaradan, on 9 Feb, 2009 - 05:02 PM, said:

Really brilliant tutorial but where's the rest of it?! You didn't even reserve any extra posts. It's been over a year so I guess it's just not happening now. :(

It was posted Sept 25 or sep 27, 2007.
Check on the list of tutorials
Was This Post Helpful? 0
  • +
  • -

#7 Haradan  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 2
  • Joined: 09-February 09

Posted 20 February 2009 - 05:57 PM

Found it: http://www.dreaminco...wtopic34015.htm

Thanks.
Was This Post Helpful? 2
  • +
  • -

#8 vanuyen  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 29-May 09

Posted 29 May 2009 - 04:42 PM

Many thanks for the clear explanation and example. :^:
Was This Post Helpful? 0
  • +
  • -

#9 rishi_k  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 08-July 09

Posted 09 July 2009 - 12:17 AM

does anyone know how to access vector elements using Iterators
Was This Post Helpful? 0
  • +
  • -

#10 wowelf  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 24-October 09

Posted 17 November 2009 - 05:14 AM

That's realy very detail and helpful! :)
Was This Post Helpful? 0
  • +
  • -

#11 pepsip77  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 14-April 10

Posted 14 April 2010 - 08:17 AM

thanks for tut :P
Was This Post Helpful? 0
  • +
  • -

#12 laserbeak43  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 129
  • Joined: 07-November 09

Posted 28 April 2010 - 05:17 AM

Thanks :bigsmile:
Was This Post Helpful? 0
  • +
  • -

#13 Jacic  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 54
  • Joined: 15-June 10

Posted 26 October 2010 - 05:03 PM

Thanks for the great tutorial. :clap: Im now moving on to part 2.
Was This Post Helpful? 0
  • +
  • -

#14 bmkrish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 24-August 11

Posted 24 August 2011 - 05:34 AM

View Postlaserbeak43, on 28 April 2010 - 05:17 AM, said:

Thanks :bigsmile:



which c++ complier supports vectors
Was This Post Helpful? -1
  • +
  • -

#15 PlasticineGuy  Icon User is offline

  • mov dword[esp+eax],0
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,436
  • Joined: 03-January 10

Posted 24 August 2011 - 10:45 PM

Every one that complies with standard C++. Just use:
#include <vector>

Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3