COMP345.5.arrays
COMP345.5.arrays
Acknowledgment
I would like to acknowledge and give my warmest thanks to Dr. Joey Paquet for his
help and support.
Note: All the teaching material in this course are courtesy of Dr. Joey Paquet.
Arrays
• Array definition:
• A collection of data elements of same type
• Identified by a sequential index
Declaring an array
• Declaring a statically allocated array allocates memory on the stack:
int score[5];
Accessing an array
• Access using index/subscript
cout << score[3];
• Note two different uses of brackets:
• In declaration, specifies the size of the array
• Anywhere else, specifies an index
Index range
• Valid range:
• Start with zero
• Zero is the first number in natural numbers
• Index is used to by the compiler to compute the offset of a value in the array stored
in the computer’s memory.
• End with size -1
• C++ will let you go beyond range
• Unpredictable results
• Neither the compiler nor the runtime system will detect these errors!
• In many cases, execution will continue as if nothing wrong happened
• Up to the programmer to stay in range
• Major source of bugs
• A major feature in the toolbox of malicious programmers…
• Improves readability
• Improves versatility
• Improves maintainability
• If size changes, only one change in the program is required (and recompilation).
• If not used, need to track required changes in many places, which is very error-
prone.
• Indicative of the limitations of static arrays, which leads to rather inflexible code.
Arrays in memory
• Statically allocated arrays are stored
as a contiguous block of memory.
• Implicitly managed using pointers
and pointer arithmetic. Given: x (int)
a+(-1*sizeof(int))
int x; a+(0*sizeof(int))
int a[4]; a[0] (int)
int b; a+(1*sizeof(int))
a[1] (int)
• The elements of a are of type int. a+(2*sizeof(int))
a[2] (int)
• However, a itself can be decayed to
a+(3*sizeof(int))
a pointer to the first element of a. a[3] (int)
(see array decay to a pointer a+(4*sizeof(int))
b (int)
explained later).
• Given an index, the compiler
calculates an address offset that
now points to the proper array
element.
• It will not check whether this points
outside of the array.
Concordia University Department of Computer Science and Software Engineering
COMP 345 - Advanced Program Design with C++ 13
Array initialization
• As simple variables can be initialized at declaration:
int price1 = 0;
int price2 {0};
int intstatarr[3] = { 1, 2, 3 };
cout << "sizeof(intstatarr) [3]: " << sizeof(intstatarr) << endl;
int int2dstatarr[2][2] = { 1, 2, 3, 4 };
cout << "sizeof(int2dstatarr) [4]: " << sizeof(int2dstatarr) << endl;
• Such a convenient feature does not exist for dynamically allocated arrays, or
anything that is a pointer.
Returning an array
• Functions cannot return static arrays in the same way simple types
are returned.
• Requires use of a pointer.
• The reason behind this is the same reason as for passing arrays as
pointers: efficiency.
char page[30][100];
Multidimensional arrays
• The elements of a one-
dimensional array are stored
as a contiguous memory int a[3][4]; int b[2][3][4];
block.
b[0][0][0] (int)
• The elements of a two- a[0][0] (int) b[0][0][1] (int)
a[0][1] (int) b[0][0][2] (int)
dimensional array are one- a[0][2] (int) b[0][0][3] (int)
b[0][1][0] (int)
dimensional arrays, which a[0][3] (int) b[0][1][1] (int)
are themselves stored as a a[1][0] (int) b[0][1][2] (int)
b[0][1][3] (int)
contiguous memory block. a[1][1] (int) b[0][2][0] (int)
a[1][2] (int) b[0][2][1] (int)
b[0][2][2] (int)
• And so on and so forth… a[1][3] (int)
b[0][2][3] (int)
a[2][0] (int) b[1][0][0] (int)
a[2][1] (int) b[1][0][1] (int)
b[1][0][2] (int)
a[2][2] (int) b[1][0][3] (int)
a[2][3] (int) b[1][1][0] (int)
b[1][1][1] (int)
b[1][1][2] (int)
b[1][1][3] (int)
b[1][2][0] (int)
b[1][2][1] (int)
b[1][2][2] (int)
b[1][2][3] (int)
Multidimensional arrays
• As the array is #include <iostream>
using namespace std;
stored in contiguous
memory space, #define HEIGHT 3
#define WIDTH 4
pointer arithmetic
int main() {
can still be used. int table[HEIGHT][WIDTH] = {2,4,6,8,10,12,14,16,18,20,22,24};
• However, rows need for (int i = 0; i < HEIGHT; i++) {
to be entirely for (int j = 0; j < WIDTH; j++) {
cout << table[i][j] << ' '; // using indexes
skipped if referring }
}
to an element of cout << endl;
further rows.
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
cout << *(*(table + i) + j) << ' '; // using array-to-pointer decay
table[0][0] (int) 2 }
}
table[0][1] (int) 4
cout << endl;
table[0][2] (int) 6
table[0][3] (int) 8 for (int i = 0; i < HEIGHT*WIDTH; i++) {
table[1][0] (int) 10 cout << *(*(table + 0) + i) << ' '; // using array-to-pointer decay
table[1][1] (int) 12 }
table[1][2] (int) 14 cout << endl;
table[1][3] (int) 16
table[2][0] (int) 18 cout << *(*(table + 1)) << endl; // 10: using array-to-pointer decay
table[2][1] (int) 20 cout << *(*(table + 1) + 7) << endl; // 24: using array-to-pointer decay
table[2][2] (int) 22 cout << *(*(table + 2) - 8) << endl; // 2: using array-to-pointer decay
table[2][3] (int) 24 int n; cin >> n;
}
• Decay is a general concept used for various purposes by which values of certain
kinds are transformed to a different kind.
• We shall here only explain decaying of a static array into a pointer.
• Dynamic arrays
• Can grow and shrink as needed.
• Implemented as pointers to dynamically allocated static array residing on the
heap.
double *d;
d = new double[10];
• Creates dynamically allocated array variable d, with ten elements of base type
double.
• The new operator for arrays does not restrict the size to be a constant.
• Stored using the same model as a static array, except that the arrays of
elements is stored on the heap instead of the stack, and thus each need to be
pointed to by a pointer and carefully managed.
Concordia University Department of Computer Science and Software Engineering
COMP 345 - Advanced Program Design with C++ 29
double *d;
d = new double[10];
… //Processing
delete [] d;
• Then use a loop to allocate 3 arrays of integers and have the pointers point to
them:
for (int i = 0; i < 3; i++)
a[i] = new int[4];
a[2][0] (int)
a[2][1] (int)
a[2][2] (int)
a[2][3] (int)
Concordia University Department of Computer Science and Software Engineering
COMP 345 - Advanced Program Design with C++ 33
other solutions
STL containers
• Some say that one should always use STL containers such as
vector instead of dynamically allocated arrays.
• These are less error-prone than basic C++ arrays, as they provide
features such as bounds checking and embed memory
allocation/deallocation mechanisms.
• STL containers allows automatic resizing of the container if
necessary.
• However, such features come with a certain cost:
• Additional data is required to manage the container’s mechanism.
• Computation time is required to manage the container’s mechanism.
• Access time is significantly higher.
• So, when a program makes heavy use of arrays and memory
consumption and efficiency are important, do not use containers.
STL containers
STL containers
• Enables the use of iterators and dynamically sized arrays.
• Multidimensional vectors:
STL containers
• Creation/destruction: STL containers are templates (covered later). Each template
defines constructors (including a copy constructor) and destructors appropriate
to the type of values stored in the container.
• Assignment: the assignment operator is overloaded for all STL templates.
• Iterators: Iterators are variables used to refer to elements of a container. They can
then be incremented and compared to other elements of the container (e.g.
begin(), end()) as loop bounds.
STL containers
• Access: the elements of an STL container can be accessed in different ways
• The at() member function can be used to refer to an element of an STL container at
a specific index. This function implements boundary checking.
• The[]operator is overloaded for all STL container, which can be used to refer to
specific elements using an index. This operator does not implement boundary
checking.
• Sequence containers also provide front() and back() method to directly access
the first and last element of the container.
• Capacity: All STL containers embed a mechanism to grow/shrink their size
dynamically as the container is used. This is a definite advantage of STL
containers (though it comes with a slight space/time overhead)
• size(): returns the number of elements in the container.
• capacity(): returns the size of the storage space currently allocated for the
container. When this capacity is exhausted and more is needed, it is automatically
expanded by the container (reallocating it storage space).
• Capacity is not guaranteed to decrease as elements are removed.
• All containers have a maximal capacity ( max_size()).
STL containers
• Modifiers: the content of STL containers can be done using a variety of methods
• insert(): inserts a value in the container in a specific index.
• erase(): removes a specific element from the container, using begin(), end()or
an iterator to identify the element. Can also be used to erase a portion of the container
(only for ordered containers).
• push_back(), push_front(): insert elements either at the front or back of the
container.
• pop_back(), pop_front(): removes the first or last element of the container.
• clear(): erases all elements from the container.
• swap(): exchanges the elements of a container with the elements the current
container.
• Warnings!
• The implementation of STL containers make use of the stored elements’ assignment
operator, constructors, copy constructor and destructor.
• Be careful when you use iterators to delete elements – yes an iterator is a pointer, but
calling delete on it deletes the iterator, not the element that it refers to. Even if it
does, it fails to update the first/last elements – use erase() instead.
• STL containers can seem simple but can lead to problems if you don’t understand how
they work internally.
Concordia University Department of Computer Science and Software Engineering
COMP 345 - Advanced Program Design with C++ 43
STL containers
References
• Y. Daniel Liang, Introduction to Programming with C++ (Chapter 7, 11), Peason,
2014, ISBN-13: 978-0133252811.
• Walter Savitch, Absolute C++ (Chapter 5, 7, 10, 19), Addison-Wesley, 2005, ISBN-
13: 9780321330239.
• Bjarne Stroustrup, The C++ Programming Language (Chapter 6, 7, 11), Addison-
Wesley, 2013, ISBN-13: 978-0321563842
• cppreference.com. std::array.
• cplusplus.com. STL containers.