C++ Arrays
An array is a contiguous, fixed-size piece of memory
- it cannot grow , cannot change size (set it when you’re declaring it !!)
-
It’s a sequence of elements
-
One BIG CHUNK of MEMORY
- Note that arrays are not C++ Objects
C-Style Array
- Heres the Syntax
type array_name[capacity];
type: is any type array_name: is an identifier capacity is the number of slots (indexing starts at 0)
- The size in memory of the array is the (type’s size * capacity)
Size of Array
#include <iostream>
using std::cout;
using std::endl;
int main() {
int guesses[] = {12, 43, 23, 56, 69};
int size = sizeof(guesses);
cout << "Size of array (Number of Bits): " << size << endl;
}
Output:
Size of array (Number of Bits): 20
- 20 bits ( 5#’s taking up 4 bits each)
Now how do we find the size of the array? (number of element)
#include <iostream>
using std::cout;
using std::endl;
int main() {
int guesses[] = {12, 43, 23, 56, 69};
int size = sizeof(guesses)/ sizeof(int);
cout << "Size of array: " << size << endl;
}
Output:
Size of array: 5
Declaring and Initializing an Array in C++
- different ways to declare and initialize
Method 1:
#include <iostream>
using std::endl;
using std::cout;
int main() {
int arr[4];
arr[0] = 20;
arr[1] = 30;
arr[2] = 40;
arr[3] = 50;
}
- Initialize elements starts with the leftmost element 0, the remaining elements are initialized to zero
Method 2:
#include <iostream>
using std::endl;
using std::cout;
int main() {
int arr[] = {20, 30, 40, 50};
}
Method 3:
#include <iostream>
using std::endl;
using std::cout;
int main() {
int arr[4] = {20, 30, 40, 50};
}
Accessing Array Elements
- How to print an Array
Method using a While Loop:
#include <iostream>
using std::endl;
using std::cout;
int main(){
int arr[] = {20, 30, 40, 50};
int n=0;
while(n<=3){
cout<<arr[n]<<endl;
n++;
}
}
Output:
20
30
40
50
Note: Iterators cannot be used on primitive type arrays, only on collections!
Method accessing the index
#include <iostream>
using std::endl;
using std::cout;
int main(){
int arr[] = {20, 30, 40, 50};
cout << arr[0] << endl;
// change index
arr[0] = 1000;
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << arr[3] << endl;
}
Output:
20
1000
30
40
50
- Cool we just changed the element at index 0 by accessing it!
What if we changed the size of our array to 10?
#include <iostream>
using std::cout;
using std::endl;
int main() {
int guesses[10] = {12, 43, 23, 56, 69};
int size = sizeof(guesses)/ sizeof(int);
for ( int i = 0; i < size; i++ )
{
cout << guesses[i] << "\t";
}
}
Output:
12 43 23 56 69 0 0 0 0 0
- Notice how, even though we didn’t configure 10 numbers (int) in our array with a size 10 array, we have extra 0’s at the end
Different Operations on Arrays
- Subscript
- Assignment
- Arithmetic
#include <iostream>
using std::endl;
using std::cout;
int main(){
int ary[2]; // Array of 2 ints
int ary[0] = 23; // Assignment
ary[1] = ary[0] + 3; // Arithmetic
}
Note: The compiler can also determine the size
Type is very important, each array needs a type so the size of memory requested can be calculated (number of elements * size of type)
- Therefore each array can only hold elements of the same type (there is some ways around this tho…)
Another Example of an Array
#include<iostream>
using std::cout; using std::endl;
int main(){
const size_t size = 5;
int ary1[size]{8,5,6,7,4};
char ary2[]{'a', 'b', 'c', 'd'}; // fixed size, 4 chars
long ary3[size]{}; // 0 initialized, each element initialized!
long ary4[size]; // uninitialized, no work done.
cout << "Indexes of Various Arrays: " << endl;
cout << "Index 0 of ary1:"<<ary1[0]<<endl;
cout << "Index 0 of ary2:"<<ary2[0]<<endl;
cout << "Index 4 of ary3:"<<ary3[4]<<endl;
cout << "Index 0 of ary4:"<<ary4[0]<<endl; // ?? not initialized
// cout << "Index 10 of ary1:"<<ary1[10] << endl; // ?? past end
for(size_t i=0; i<size; ++i)
cout << "Index"<<i<<", value:"<<ary1[i] << endl;;
// range based for, OK, const value of size
for (auto element : ary1)
cout << "int element:"<<element<<", ";
cout << endl;
for(auto element : ary2)
cout << "char element:"<<element<<", ";
cout << endl;
// subscript assignment OK
ary3[0]=1234;
for(size_t j=1; j<size; j++)
ary3[j] = ary3[j-1] * 2;
for (size_t j=0; j<size; j++)
cout << "Index"<<j<<", value:"<<ary3[j] << endl;
}
Output:
Index 0 of ary1:8
Index 0 of ary2:a
Index 4 of ary3:0
Index 0 of ary4:4543734386
Index0, value:8
Index1, value:5
Index2, value:6
Index3, value:7
Index4, value:4
int element:8, int element:5, int element:6, int element:7, int element:4,
char element:a, char element:b, char element:c, char element:d,
Index0, value:1234
Index1, value:2468
Index2, value:4936
Index3, value:9872
Index4, value:19744
Advantages of Arrays in C++
- Random Access of elemtns using the array index []
- East access to all the elements
- Traversal through the array is easy using a loop
- Can easily Sort
Disadvantages of Arrays in C++
-
Allows for a fixed number of elements, which has to be decided at the time of declaring and array
-
Insertion and deletion of elements can be costly
Arrays and Pointers
-
NOTE Arrays DO NOT remember their length when passed!
- C++ is too sensitive to know the size of the array
- If the compiler knows the size then it allows you to do things like for-each loops
- If the compiler cannot know the size, it treats it like a pointer
-
Arrays and Pointers are two different things
- Arrays have no methods, C++ does provide functions begin() and end() (if the compiler knows the array size) (they’re functions NOT methods)
- You can treat a pointer as an iterator if you want to run generic algorithms on an array
- no begin or end method, but an array pointer IS an iterator
Example using Pointer to iterate/print Array:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
const size_t size = 5;
int arr[size]{8,5,6,7,4};
for (int *i = arr; i < (arr+size); i++)
{
cout << "Element: " << *i << ", ";
}
cout << endl; // end line
}
Output:
Element: 8, Element: 5, Element: 6, Element: 7, Element: 4,
Example using sort() and copy() algorithms on the Array:
-
Note that the Front Pointer points to the first index in the array, while the Back Pointer points to one index past the last. Hence in the following example image below:
-
In this example we use the sort() and the copy algorithm on the array to 1. Sort the array in-order and 2. To *copy& and print the sorted array out.
#include <iostream>
using std::cout;
using std::endl;
#include<algorithm>
using std::copy; using std::sort; using std::transform;
#include<iterator>
using std::ostream_iterator; using std::begin; using std::end;
int main()
{
const size_t size = 5;
int arr[size]{8,5,6,7,4};
int *pointer_array_front = arr;
int *pointer_array_back = arr+size;
cout << "Front Pointer: " << pointer_array_front << endl;
cout << "Front Value: " << *pointer_array_front << endl;
cout << "One Past End Pointer: " << pointer_array_back << endl;
cout << "Back Value: " << *pointer_array_back << endl;
// Array Pointer is an iterator
sort(pointer_array_front, pointer_array_back);
copy(pointer_array_front, pointer_array_back, ostream_iterator<int>(cout, ", "));
cout << endl;
}
Output:
Front Pointer: 0x7ffeedc695d0
Front Value: 8
One Past End Pointer: 0x7ffeedc695e4
Back Value: 32766
4, 5, 6, 7, 8,
- We can see where the address and the value that the Front Pointer is pointing too
- The last back pointer value is some random number -> 32766
Example using begin() and end() functions with the transform algorithm on the Array:
- Note: begin() and end() functions (NOT METHODS) do work if the complier knows the size of the array
#include <iostream>
using std::cout;
using std::endl;
#include<algorithm>
using std::copy; using std::sort; using std::transform;
#include<iterator>
using std::ostream_iterator; using std::begin; using std::end;
int main()
{
const size_t size = 5;
int arr[size]{8,5,6,7,4};
int *pointer_array_front = arr;
int *pointer_array_back = arr+size;
transform(begin(arr), end(arr), ostream_iterator<int>(cout, ", "), [] (int x) {return x*2;});
cout << endl;
}
Output:
16, 10, 12, 14, 8,
Arrays and Functions
- There are 3 ways to pass an array to a function, note that is’s always a pointer or a reference and NEVER a copy
First Way:
- Pass array, it’s implicity a pointer
Syntax:
int sum(int arr[], int size)
- [] indicates the parameter is an array
- int size is the size of the array
- It’s a pointer!
#include<iostream>
using std::cout; using std::endl;
#include<sstream>
using std::ostringstream;
#include<string>
using std::string;
int sum (int arr[], int size){
int sum = 0;
for(int i=0; i<size; i++){
sum += arr[i];
}
return sum;
}
int main()
{
int arr[]{8,5,6,7,4};
int size = sizeof(arr) / sizeof(int);
cout << sum(arr, size) << endl;
}
Output:
30
Second Way (directly as a pointer)
Syntax:
int sum(int *arr, int size)
- Passed in as a pointer
#include<iostream>
using std::cout; using std::endl;
#include<sstream>
using std::ostringstream;
#include<string>
using std::string;
int sum (int *arr, int size){
int sum = 0;
for(int i=0; i<size; i++){
sum += arr[i]; // Same thing
// sum += *(arr+1);
}
return sum;
}
int main()
{
int arr[]{8,5,6,7,4};
int size = sizeof(arr) / sizeof(int);
cout << sum(arr, size) << endl;
}
Output:
30
Third Way
- If you set the size (somehow) in the function call itself, then the compiler can figure out how to do things like for-each loop
#include<iostream>
using std::cout; using std::endl;
#include<string>
using std::string;
int sum (const int (&arr)[5]){
int sum = 0;
for (auto &element : arr )
{
sum += element;
}
return sum;
}
int main()
{
int arr[]{8,5,6,7,4};
cout << sum(arr) << endl;
}
Output:
30
Lets Template the Size, so we don’t have to indicate it!:
#include<iostream>
using std::cout; using std::endl;
#include<string>
using std::string;
// let template deduce size, we don't have to say!!
template<typename Type, size_t Size>
int sum (const Type (&arr)[Size]){
Type sum = 0;
cout << "Sizeof array (template size) : " << sizeof(arr) << endl;
for (auto element : arr )
{
sum += element;
}
return sum;
}
int main()
{
int arr[]{8,5,6,7,4,20,3,69,15};
cout << sum(arr) << endl;
}
Output:
Sizeof array (template size) : 36
137
Multidimensional Arrays
Example of an Multidimensional Array
- Need a nested for loop to iterate through
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int grades[][3] =
{
{1,2,3},
{4,5,6},
{7,8,9}
};
for (int r = 0; r < 3; r++)
{
for ( int c = 0; c < 3; c++ )
{
cout << grades[r][c] << "\t";
}
cout << "\n";
};
}
Output:
1 2 3
4 5 6
7 8 9
Dynamic Memory
Run Time vs Compile Time
-
Where compile time is known at the time of running the compiler to make an executable, while run time is known when the user actually runs the exectuable
-
STL Objects are the best, they know how to get more memory during runtime( think vectors, maps, etc.), while things like arrays, fixed-size non-object -> they’re fixed size at compile time
-
For normal variables, memory is automatically allocated and deallocated, but for things like pointers -> int *p = new int[10], it’s up to us as programmers to deallocate memory when no longer needed, if we don’t then it causes memory leak.
-
We can manually perform memory allocation
new and delete Keywords
new
new type(init)
- the new operator denotes a request to allocate new memory of indicated type on Free Store (can optionally provide an init, not required)
- Return a pointer to the new memory
Example of a pointer-variable
int *p = new int; // Request for memory with the new keyword
We can alocatre a block (an array) of memory
int *p = new int[5]
- This code above dynamically allocates memory for 5 integers continuously of type int and returns pointer to the first element in the sequence, which is assigned to p (a pointer).
#include<iostream>
using std::cout; using std::endl; using std::cin;
// Dynamic Arrays
int main(){
// Main purpose is to allocate memory size of allocation in Bytes
int size;
cout << "Please enter a Size of an Array: ";
cin >> size;
int * myArray = new int [size]; // size that we enter
for (int i =0; i<size; i++)
{
cout << "Array[" << i << "]";
cin >> myArray[i];
}
for (int i =0; i<size; i++)
{
// write out elements of our array
cout << myArray[i] << " ";
}
}
Output
I wanted an Array or size 5, and then I input the following numbers: 6,9,7,3, and 12
Please enter a Size of an Array: 5
Array[0]6
Array[1]9
Array[2]7
Array[3]3
Array[4]12
6 9 7 3 12
delete
- Since it’s our responsibity as a programmer to deallocate dynamically allocated memory, this is where we use the delete keyword
delete pointer-variable; // release memory pointed by the pointer-variable
- Deletion of an object pointed to by the pointer, releases memory
Here is an example of deleting an array of all elements, the ptr points to the beginning of the memory array to be deleted
delete [] ptr;
Lets deallocate the memory that we have allocated from the array:
#include<iostream>
using std::cout; using std::endl; using std::cin;
// Dynamic Arrays
int main(){
// Main purpose is to allocate memory size of allocation in Bytes
int size;
cout << "Please enter a Size of an Array: ";
cin >> size;
int * myArray = new int [size]; // size that we enter
for (int i =0; i<size; i++)
{
cout << "Array[" << i << "]";
cin >> myArray[i];
}
for (int i =0; i<size; i++)
{
// write out elements of our array
cout << myArray[i] << " ";
}
delete[] myArray; // delete the memory that we allocated for our array
myArray = NULL; // point to nothing, good practice
}
Note: Each time you write new you must write delete
Growing Array Example
#include <iostream>
using std::cout; using std::endl;
#include <algorithm>
using std::copy;
#include <iterator>
using std::ostream_iterator;
void print_array(int * array, size_t size) {
for (int i =0; i<size; i++)
{
// write out elements of our array
cout << array[i] << " ";
}
cout << endl;
// Or
// copy(array, array + size, ostream_iterator<int>(cout, " "));
}
void double_size(int * (&array), size_t & size) {
// double the size of the array
size_t new_size = size * 2; // Double Size
int * array2 = new int[new_size]{}; // new Keyword Create new array
copy(array, array + size, array2); // Copy elments of array1 to array2
size = new_size; // Update Size
delete [] array; // delete Keyword
array = array2;
}
int main() {
const size_t size = 2;
int * array = new int[size];
array[0] = 9;
array[1] = 7;
cout << "Original Array: " << endl;
print_array(array, size);
size_t new_size = size + 1;
int * array2 = new int[new_size]{};
copy(array, array + size, array2); // Copy elements of array1 to array2
// Never use array after this point, so delete
delete [] array;
cout << "Array after increasing the size by 1: " << endl;
print_array(array2, new_size);
cout << "Array after adding new element: " << endl;
array2[2] = 3;
print_array(array2, new_size);
// Using Double function
cout << "Double!" << endl;
double_size(array2, new_size);
// Print out our doubled array:
print_array(array2, new_size);
delete [] array2;
}
Output:
9 7
9 7 0
9 7 3
Double!
9 7 3 0 0 0
Dynamic Array Example
#include<iostream>
using std::cout; using std::endl; using std::cin; using std::ostream;
#include<iomanip>
using std::setw;
#include<string>
using std::string;
class MyClass{
private:
long long_;
int int_;
string str_;
public:
MyClass(): long_(0), int_(0), str_("default ctor") {};
MyClass(long l, int i, string s): long_(l), int_(i), str_(s) {};
friend ostream& operator<<(ostream&, const MyClass&);
};
ostream& operator<<(ostream &out, const MyClass &c){
out << "l:"<< c.long_ << ", i:" << c.int_ << ", s:" << c.str_;
return out;
}
void fill(int *ary, size_t sz, int val){
for (size_t i=0; i<sz; ++i)
ary[i] = val+i;
}
// print array as a block
ostream& dump (ostream& out, int ary[], size_t sz, size_t width=5){
for(size_t i=0; i < sz; ++i){
out << setw(width) << *(ary + i);
if (i%10 != 9 && i != sz-1)
out << ", ";
else
out << endl;
}
out << endl;
return out;
}
int main (){
size_t sz=5;
int ary1[sz];
fill(ary1, sz, 10);
dump(cout, ary1, sz);
// basic new
long *lptr1, *lptr2;
MyClass *mcptr, *mcptr2;
lptr1 = new long; // uninitialized
lptr2 = new long{1234567}; // initialized
mcptr = new MyClass; // default constructor
mcptr2 = new MyClass(123456, 123, "3param ctor");
cout << "lptr1:"<< *lptr1 << endl;
cout << "lptr2:"<< *lptr2 << endl;
cout << "MyClass default:"<< *mcptr << endl;
cout << "MyClass 3 param:"<< *mcptr2 << endl;
// delete them when done
delete lptr1;
delete lptr2;
delete mcptr;
delete mcptr2;
// dynamic array
size_t size;
cout << "How big to make the array:";
cin >> size;
// not an array type, only a pointer
// long *ary = new long[size]; // not initialized
int *ary = new int[size]{}; // initialize all!
fill(ary, size, 10);
dump(cout, ary, size);
cout << "1:"<<ary[0]<<endl;
cout << "n-1:"<<ary[size-1]<<endl;
cout << "Size:"<<sizeof(ary)<<endl; //pointer,not array type!
// if you make it, you must delete it. Note []
delete [] ary;
}
- Let’s make the array 1000!
Output
10, 11, 12, 13, 14
lptr1:0
lptr2:1234567
MyClass default:l:0, i:0, s:default ctor
MyClass 3 param:l:123456, i:123, s:3param ctor
How big to make the array:1000
10, 11, 12, 13, 14, 15, 16, 17, 18, 19
20, 21, 22, 23, 24, 25, 26, 27, 28, 29
30, 31, 32, 33, 34, 35, 36, 37, 38, 39
40, 41, 42, 43, 44, 45, 46, 47, 48, 49
50, 51, 52, 53, 54, 55, 56, 57, 58, 59
60, 61, 62, 63, 64, 65, 66, 67, 68, 69
70, 71, 72, 73, 74, 75, 76, 77, 78, 79
80, 81, 82, 83, 84, 85, 86, 87, 88, 89
90, 91, 92, 93, 94, 95, 96, 97, 98, 99
100, 101, 102, 103, 104, 105, 106, 107, 108, 109
110, 111, 112, 113, 114, 115, 116, 117, 118, 119
120, 121, 122, 123, 124, 125, 126, 127, 128, 129
130, 131, 132, 133, 134, 135, 136, 137, 138, 139
140, 141, 142, 143, 144, 145, 146, 147, 148, 149
150, 151, 152, 153, 154, 155, 156, 157, 158, 159
160, 161, 162, 163, 164, 165, 166, 167, 168, 169
170, 171, 172, 173, 174, 175, 176, 177, 178, 179
180, 181, 182, 183, 184, 185, 186, 187, 188, 189
190, 191, 192, 193, 194, 195, 196, 197, 198, 199
200, 201, 202, 203, 204, 205, 206, 207, 208, 209
210, 211, 212, 213, 214, 215, 216, 217, 218, 219
220, 221, 222, 223, 224, 225, 226, 227, 228, 229
230, 231, 232, 233, 234, 235, 236, 237, 238, 239
240, 241, 242, 243, 244, 245, 246, 247, 248, 249
250, 251, 252, 253, 254, 255, 256, 257, 258, 259
260, 261, 262, 263, 264, 265, 266, 267, 268, 269
270, 271, 272, 273, 274, 275, 276, 277, 278, 279
280, 281, 282, 283, 284, 285, 286, 287, 288, 289
290, 291, 292, 293, 294, 295, 296, 297, 298, 299
300, 301, 302, 303, 304, 305, 306, 307, 308, 309
310, 311, 312, 313, 314, 315, 316, 317, 318, 319
320, 321, 322, 323, 324, 325, 326, 327, 328, 329
330, 331, 332, 333, 334, 335, 336, 337, 338, 339
340, 341, 342, 343, 344, 345, 346, 347, 348, 349
350, 351, 352, 353, 354, 355, 356, 357, 358, 359
360, 361, 362, 363, 364, 365, 366, 367, 368, 369
370, 371, 372, 373, 374, 375, 376, 377, 378, 379
380, 381, 382, 383, 384, 385, 386, 387, 388, 389
390, 391, 392, 393, 394, 395, 396, 397, 398, 399
400, 401, 402, 403, 404, 405, 406, 407, 408, 409
410, 411, 412, 413, 414, 415, 416, 417, 418, 419
420, 421, 422, 423, 424, 425, 426, 427, 428, 429
430, 431, 432, 433, 434, 435, 436, 437, 438, 439
440, 441, 442, 443, 444, 445, 446, 447, 448, 449
450, 451, 452, 453, 454, 455, 456, 457, 458, 459
460, 461, 462, 463, 464, 465, 466, 467, 468, 469
470, 471, 472, 473, 474, 475, 476, 477, 478, 479
480, 481, 482, 483, 484, 485, 486, 487, 488, 489
490, 491, 492, 493, 494, 495, 496, 497, 498, 499
500, 501, 502, 503, 504, 505, 506, 507, 508, 509
510, 511, 512, 513, 514, 515, 516, 517, 518, 519
520, 521, 522, 523, 524, 525, 526, 527, 528, 529
530, 531, 532, 533, 534, 535, 536, 537, 538, 539
540, 541, 542, 543, 544, 545, 546, 547, 548, 549
550, 551, 552, 553, 554, 555, 556, 557, 558, 559
560, 561, 562, 563, 564, 565, 566, 567, 568, 569
570, 571, 572, 573, 574, 575, 576, 577, 578, 579
580, 581, 582, 583, 584, 585, 586, 587, 588, 589
590, 591, 592, 593, 594, 595, 596, 597, 598, 599
600, 601, 602, 603, 604, 605, 606, 607, 608, 609
610, 611, 612, 613, 614, 615, 616, 617, 618, 619
620, 621, 622, 623, 624, 625, 626, 627, 628, 629
630, 631, 632, 633, 634, 635, 636, 637, 638, 639
640, 641, 642, 643, 644, 645, 646, 647, 648, 649
650, 651, 652, 653, 654, 655, 656, 657, 658, 659
660, 661, 662, 663, 664, 665, 666, 667, 668, 669
670, 671, 672, 673, 674, 675, 676, 677, 678, 679
680, 681, 682, 683, 684, 685, 686, 687, 688, 689
690, 691, 692, 693, 694, 695, 696, 697, 698, 699
700, 701, 702, 703, 704, 705, 706, 707, 708, 709
710, 711, 712, 713, 714, 715, 716, 717, 718, 719
720, 721, 722, 723, 724, 725, 726, 727, 728, 729
730, 731, 732, 733, 734, 735, 736, 737, 738, 739
740, 741, 742, 743, 744, 745, 746, 747, 748, 749
750, 751, 752, 753, 754, 755, 756, 757, 758, 759
760, 761, 762, 763, 764, 765, 766, 767, 768, 769
770, 771, 772, 773, 774, 775, 776, 777, 778, 779
780, 781, 782, 783, 784, 785, 786, 787, 788, 789
790, 791, 792, 793, 794, 795, 796, 797, 798, 799
800, 801, 802, 803, 804, 805, 806, 807, 808, 809
810, 811, 812, 813, 814, 815, 816, 817, 818, 819
820, 821, 822, 823, 824, 825, 826, 827, 828, 829
830, 831, 832, 833, 834, 835, 836, 837, 838, 839
840, 841, 842, 843, 844, 845, 846, 847, 848, 849
850, 851, 852, 853, 854, 855, 856, 857, 858, 859
860, 861, 862, 863, 864, 865, 866, 867, 868, 869
870, 871, 872, 873, 874, 875, 876, 877, 878, 879
880, 881, 882, 883, 884, 885, 886, 887, 888, 889
890, 891, 892, 893, 894, 895, 896, 897, 898, 899
900, 901, 902, 903, 904, 905, 906, 907, 908, 909
910, 911, 912, 913, 914, 915, 916, 917, 918, 919
920, 921, 922, 923, 924, 925, 926, 927, 928, 929
930, 931, 932, 933, 934, 935, 936, 937, 938, 939
940, 941, 942, 943, 944, 945, 946, 947, 948, 949
950, 951, 952, 953, 954, 955, 956, 957, 958, 959
960, 961, 962, 963, 964, 965, 966, 967, 968, 969
970, 971, 972, 973, 974, 975, 976, 977, 978, 979
980, 981, 982, 983, 984, 985, 986, 987, 988, 989
990, 991, 992, 993, 994, 995, 996, 997, 998, 999
1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009
1:10
n-1:1009
Size:8
Another Example
#include<iostream>
using std::cout; using std::endl; using std::cin; using std::ostream;
#include<iomanip>
using std::setw;
#include<string>
using std::string;
void fill(int ary[], int size, int value)
{ // Fill Array with values
for (int i=0; i<size; ++i)
{
ary[i] = value+i;
}
}
ostream& dump (ostream& out, int ary[], int size, int width=5){
//print array as a block
for(int i=0; i < size; ++i){
out << setw(width) << *(ary + i);
if (i%10 != 9 && i != size-1)
out << ", ";
else
out << endl;
}
out << endl;
return out;
}
int main (){
// dynamic array
int size;
cout << "How Big to make the array:";
cin >> size;
// not an array type, only a pointer
// long *ary = new long[size]; // not initialized
int *ary = new int[size]{}; // initialize all!
fill(ary, size, 10);
dump(cout, ary, size);
cout << "1:"<<ary[0]<<endl;
cout << "n-1:"<<ary[size-1]<<endl;
cout << "Size:"<<sizeof(ary)<<endl; //pointer,not array type!
// if you make it, you must delete it. Note []
delete [] ary;
}
Output:
How Big to make the array:100
10, 11, 12, 13, 14, 15, 16, 17, 18, 19
20, 21, 22, 23, 24, 25, 26, 27, 28, 29
30, 31, 32, 33, 34, 35, 36, 37, 38, 39
40, 41, 42, 43, 44, 45, 46, 47, 48, 49
50, 51, 52, 53, 54, 55, 56, 57, 58, 59
60, 61, 62, 63, 64, 65, 66, 67, 68, 69
70, 71, 72, 73, 74, 75, 76, 77, 78, 79
80, 81, 82, 83, 84, 85, 86, 87, 88, 89
90, 91, 92, 93, 94, 95, 96, 97, 98, 99
100, 101, 102, 103, 104, 105, 106, 107, 108, 109
1:10
n-1:109
Size:8
Leaking Memory
-
Memory leakage occurs in C++ when programmers allocates memory by using new keyword and forgets to deallocate the memory by using delete() function or delete[] operator. One of the most memory leakage occurs in C++ by using wrong delete operator.
-
It’s on you to free/delete memory that you have acquired
-
Can you avoid this? Yes by using STL containers
Leaking Memory Example
#include<cstddef>
using std::size_t;
#include<iostream>
using std::cout; using std::endl; using std::cin;
#include<string>
using std::string;
int main (){
int reps = 1024;
const size_t chunk = 1048576; // be careful!!!
long last;
string s;
for(int i=0;i<reps;i++){
long *ary = new long[chunk]; // leak memory here each iteration
ary[0] = 1;
for (size_t j=1; j < chunk; ++j)
ary[j] = ary[j-1] + 1;
last = ary[chunk-1];
}
cout << last << endl;
cout << "A string please:";
cin >> s;
}
Output:
Last Example
#include<iostream>
using std::cout; using std::endl; using std::ostream;
long* fn1(size_t sz, long start, long inc ){
auto ptr = new long[sz];
ptr[0]=start;
for(size_t i=1; i<sz; i++)
ptr[i]=ptr[i-1]+inc;
return ptr;
}
ostream& print(ostream& out, long ary[], size_t sz){
for(size_t i=0;i<sz;i++){
out << ary[i];
if (i < sz-1)
out << ", ";
}
out << endl;
return out;
}
int main (){
long *ptr_l;
// double *ptr_d;
size_t sz=10;
ptr_l = fn1(sz, 100, 10);
cout << ptr_l << endl;
print(cout, ptr_l, 10) << endl;
// leak without this, even though allocated in fn1
delete [] ptr_l;
}
Output
0x7f9177c05980
100, 110, 120, 130, 140, 150, 160, 170, 180, 190