Chapter 18 Vectors and Arrays

28
Chapter 18 Chapter 18 Vectors and Arrays Vectors and Arrays Bjarne Stroustrup Bjarne Stroustrup www.stroustrup.com/Programming www.stroustrup.com/Programming

description

Chapter 18 Vectors and Arrays. Bjarne Stroustrup www.stroustrup.com/Programming. Abstract. arrays, pointers, copy semantics, elements access, references Next lecture: parameterization of a type with a type (templates), and range checking (exceptions). Overview. Vector revisited - PowerPoint PPT Presentation

Transcript of Chapter 18 Vectors and Arrays

Page 1: Chapter 18 Vectors and  Arrays

Chapter 18Chapter 18Vectors and ArraysVectors and Arrays

Bjarne Stroustrup Bjarne Stroustrup www.stroustrup.com/Programmingwww.stroustrup.com/Programming

Page 2: Chapter 18 Vectors and  Arrays

AbstractAbstract

arrays, pointers, copy semantics, elements arrays, pointers, copy semantics, elements access, referencesaccess, references

Next lecture: parameterization of a type with a Next lecture: parameterization of a type with a type (templates), and range checking type (templates), and range checking (exceptions).(exceptions).

22Stroustrup/ProgrammingStroustrup/Programming

Page 3: Chapter 18 Vectors and  Arrays

OverviewOverview Vector revisitedVector revisited

How are they implemented?How are they implemented? Pointers and free storePointers and free store DestructorsDestructors Copy constructor and copy assignmentCopy constructor and copy assignment ArraysArrays Array and pointer problemsArray and pointer problems Changing sizeChanging size TemplatesTemplates Range checking and exceptionsRange checking and exceptions

33Stroustrup/ProgrammingStroustrup/Programming

Page 4: Chapter 18 Vectors and  Arrays

ReminderReminder Why look at the vector implementation?Why look at the vector implementation?

To see how the standard library vector really worksTo see how the standard library vector really works To introduce basic concepts and language featuresTo introduce basic concepts and language features

Free store (heap)Free store (heap) CopyingCopying Dynamically growing data structuresDynamically growing data structures

To see how to directly deal with memoryTo see how to directly deal with memory To see the techniques and concepts you need to understand CTo see the techniques and concepts you need to understand C

Including the dangerous onesIncluding the dangerous ones To demonstrate class design techniquesTo demonstrate class design techniques To see examples of “neat” code and good designTo see examples of “neat” code and good design

44Stroustrup/ProgrammingStroustrup/Programming

Page 5: Chapter 18 Vectors and  Arrays

vectorvector// // a very simplifieda very simplified vector vector of of doubledoubles (as far as we got in chapter 17)s (as far as we got in chapter 17)::

class vector {class vector {int sz;int sz; // // the sizethe sizedouble* elem;double* elem; // // pointer to elementspointer to elements

public:public:vector(int s) :sz(s), elem(new double[s]) { }vector(int s) :sz(s), elem(new double[s]) { } // // constructorconstructor

// // newnew allocates allocates memorymemory~vector() { delete[ ] elem; }~vector() { delete[ ] elem; } // // destructordestructor

// // delete[] delete[] deallocates memorydeallocates memory

double get(int n) { return elem[n]; } double get(int n) { return elem[n]; } // // access: readaccess: readvoid set(int n, double v) { elem[n]=v; }void set(int n, double v) { elem[n]=v; } // // access: writeaccess: writeint size() const { return sz; }int size() const { return sz; } // // the number of elementsthe number of elements

};};

55Stroustrup/ProgrammingStroustrup/Programming

Page 6: Chapter 18 Vectors and  Arrays

A problemA problem Copy doesn’t work as we would have hoped (expected?)Copy doesn’t work as we would have hoped (expected?)void f(int n)void f(int n){{

vector v(n);vector v(n); // // define adefine a vector vector vector v2 = v; vector v2 = v; // // what happens here?what happens here?

// // what would we like to happen?what would we like to happen?vector v3; vector v3; v3 = v;v3 = v; // // what happens here?what happens here?

// // what would we like to happen?what would we like to happen?// // ……

}} IIdeally:deally: v2 v2 andand v3 v3 become copies of become copies of vv (that is, (that is, = = makes copiesmakes copies))

And all memory is returned to the free store upon exit fromAnd all memory is returned to the free store upon exit from f() f() TThat’s what the standardhat’s what the standard vector vector does,does,

but it’s not what happens for our still-too-simplebut it’s not what happens for our still-too-simple vector vector66Stroustrup/ProgrammingStroustrup/Programming

Page 7: Chapter 18 Vectors and  Arrays

Naïve copy initialization (the default)Naïve copy initialization (the default)void f(int n)void f(int n){{

vector v1(n);vector v1(n);vector v2 = v1; vector v2 = v1; // // initialization:initialization:

// // by default, a copy of a class copies its membersby default, a copy of a class copies its members// // so so szsz and and elem elem are copiedare copied

}}

77

3

3

v1:

v2:

Disaster when we leave f()! v1’s elements are deleted twice (by the destructor)

Stroustrup/ProgrammingStroustrup/Programming

Page 8: Chapter 18 Vectors and  Arrays

Naïve copy assignment (the default)Naïve copy assignment (the default)void f(int n)void f(int n){{

vector v1(n);vector v1(n);vector v2(4);vector v2(4);v2 = v1;v2 = v1; // // assignment :assignment :

// // by default, a copy of a class copies its membersby default, a copy of a class copies its members// // so so szsz and and elem elem are copiedare copied

}}

88

3

3

v1:

v2:

Disaster when we leave f()!v1’s elements are deleted twice (by the destructor)memory leak: v2’s elements are not deleted

2nd

1st

Stroustrup/ProgrammingStroustrup/Programming

Page 9: Chapter 18 Vectors and  Arrays

Copy constructor (initialization)Copy constructor (initialization)class vector {class vector {

int sz;int sz;

double* elem;double* elem;

public:public:

vector(const vector&) ;vector(const vector&) ; // // copy constructor: define copycopy constructor: define copy

// // ……

};};

vector:: vector(const vector& a)vector:: vector(const vector& a)

:sz(a.sz), elem(new double[a.sz]):sz(a.sz), elem(new double[a.sz])

// // allocate space for elements, then initialize them (by copying)allocate space for elements, then initialize them (by copying)

{{

for (int i = 0; i<sz; ++i) elem[i] = a.elem[i];for (int i = 0; i<sz; ++i) elem[i] = a.elem[i];

}}

99Stroustrup/ProgrammingStroustrup/Programming

Page 10: Chapter 18 Vectors and  Arrays

Copy with copy constructorCopy with copy constructor

void f(int n)void f(int n){{

vector v1(n);vector v1(n);vector v2 = v1;vector v2 = v1; // // copy using the copy constructorcopy using the copy constructor

// // a for loop copies each value from v1 into v2a for loop copies each value from v1 into v2}}

1010

3

3

v1:

v2:

The destructor correctly deletes all elements (once only)

Stroustrup/ProgrammingStroustrup/Programming

Page 11: Chapter 18 Vectors and  Arrays

Copy assignmentCopy assignmentclass vector {class vector {

int sz;int sz;double* elem;double* elem;

public:public:vector& operator=(const vector& a);vector& operator=(const vector& a); // // copy assignment: define copycopy assignment: define copy

// // ……};};

x=a;x=a;

1111

21 3 4

48 2

48 2a:

1st

2nd

Operator = must copy a’s elements

x:

Memory leak? (no)

Stroustrup/ProgrammingStroustrup/Programming

Page 12: Chapter 18 Vectors and  Arrays

Copy assignmentCopy assignment

vector& vector::operator=(const vector& a)vector& vector::operator=(const vector& a)// // like copy constructor, but we must deal with old elementslike copy constructor, but we must deal with old elements// // make a copy of make a copy of aa then replace the current then replace the current szsz and and elemelem with with aa’s’s

{{double* p = new double[a.sz];double* p = new double[a.sz]; // // allocate new spaceallocate new spacefor (int i = 0; i<a.sz; ++i) p[i] = a.elem[i];for (int i = 0; i<a.sz; ++i) p[i] = a.elem[i]; // // copy elementscopy elementsdelete[ ] elem;delete[ ] elem; // // deallocate old spacedeallocate old spacesz = a.sz;sz = a.sz; // // set new sizeset new sizeelem = p;elem = p; // // set new elementsset new elementsreturn *this; return *this; //// return a self-referencereturn a self-reference

//// TheThe this this pointer is explained in Lecture 19pointer is explained in Lecture 19//// and in 17.10 and in 17.10

}}

1212Stroustrup/ProgrammingStroustrup/Programming

Page 13: Chapter 18 Vectors and  Arrays

Copy with copy assignmentCopy with copy assignmentvoid f(int n)void f(int n){{

vector v1(n);vector v1(n);vector v2(4);vector v2(4);v2 = v1;v2 = v1; // // assignmentassignment

}}

1313

3 6 4224

3

v1:

v2:

2nd

1st

42246

delete[ ]d by =

No memory Leak

Stroustrup/ProgrammingStroustrup/Programming

Page 14: Chapter 18 Vectors and  Arrays

Copy terminologyCopy terminology Shallow copy: copy only a pointer so that the two pointers Shallow copy: copy only a pointer so that the two pointers

now refer to the same objectnow refer to the same object What pointers and references doWhat pointers and references do

Deep copy: copy the pointer and also what it points to so that Deep copy: copy the pointer and also what it points to so that the two pointers now each refer to a distinct objectthe two pointers now each refer to a distinct object What What vectorvector, , stringstring, etc. do, etc. do Requires copy constructors and copy assignments for container classesRequires copy constructors and copy assignments for container classes

1414

x:

y: Copy of y:y:

Copy of x:x:Copy of x:

Shallow copy Deep copy

Stroustrup/ProgrammingStroustrup/Programming

Page 15: Chapter 18 Vectors and  Arrays

Deep and shallow copyDeep and shallow copy

vector<int> v1;vector<int> v1;v1.push_back(2);v1.push_back(2);v1.push_back(4);v1.push_back(4);vector<int> v2 = v1;vector<int> v2 = v1; // // deep copy (deep copy (v2v2 gets its own copy of gets its own copy of v1v1’s elements)’s elements)v2[0] = 3;v2[0] = 3; // // v1[0] v1[0] is still 2is still 2

1515

r1:r2: b:int b = 9; int b = 9;

int& r1 = b;int& r1 = b;

int& r2 = r1;int& r2 = r1; // // shallow copy (shallow copy (r2 r2 refers to the same variable asrefers to the same variable as r1 r1))

r2 = 7;r2 = 7; // // b b becomes 7becomes 7

4

v1: v2:

2

4

2 2

Stroustrup/ProgrammingStroustrup/Programming

Page 16: Chapter 18 Vectors and  Arrays

ArraysArrays Arrays don’t have to be on the free storeArrays don’t have to be on the free store

char ac[7];char ac[7]; // // global array – “lives” forever – “in static storage”global array – “lives” forever – “in static storage”int max = 100;int max = 100;int ai[max];int ai[max];

int f(int n)int f(int n){{

char lc[20]; // char lc[20]; // local array – “lives” until the end of scope – on stacklocal array – “lives” until the end of scope – on stackint li[60];int li[60];double lx[n]; // double lx[n]; // error: a local array size must be known at compile timeerror: a local array size must be known at compile time

//// vector<double> lx(n);vector<double> lx(n); would work would work//// ……

}}

1616Stroustrup/ProgrammingStroustrup/Programming

Page 17: Chapter 18 Vectors and  Arrays

Address of: &Address of: & You can get a pointer to any objectYou can get a pointer to any object

not just to objects on the free storenot just to objects on the free storeint a;int a;char ac[20];char ac[20];

void f(int n)void f(int n){{

int b;int b;int* p = &b;int* p = &b; // // pointer to individual variablepointer to individual variablep = &a;p = &a;char* pc = ac;char* pc = ac; // // the name of an array names a pointer to its first elementthe name of an array names a pointer to its first elementpc = &ac[0];pc = &ac[0]; //// equivalent to pc = acequivalent to pc = acpc = &ac[n];pc = &ac[n]; //// pointer to ac’s npointer to ac’s nthth element (starting at 0 element (starting at 0 thth))

//// warning: range is not checkedwarning: range is not checked// …// …

}}

1717

p:

a: ac:

pc:

Stroustrup/ProgrammingStroustrup/Programming

Page 18: Chapter 18 Vectors and  Arrays

Arrays (often) convert to pointersArrays (often) convert to pointersvoid f(int pi[ ])void f(int pi[ ]) // // equivalent toequivalent to void f(int* pi) void f(int* pi) {{

int a[ ] = { 1, 2, 3, 4 };int a[ ] = { 1, 2, 3, 4 };int b[ ] = a;int b[ ] = a; // // error: copy isn’t defined for arrayserror: copy isn’t defined for arraysb = pi;b = pi; // // error: copy isn’t defined for arrays. Think of aerror: copy isn’t defined for arrays. Think of a

// // (non-argument) array name as an immutable pointer(non-argument) array name as an immutable pointerpi = a;pi = a; // // ok: but it doesn’t copy: ok: but it doesn’t copy: pipi now points to now points to aa’s first element’s first element

// // Is this a memory leak? (maybe)Is this a memory leak? (maybe)int* p = a;int* p = a; // // pp points to the first element of points to the first element of aaint* q = pi;int* q = pi; // // q q points to the first element of points to the first element of aa

}}

1818

1

pi:

a: 2 3 4

p:

1st

2nd

q:

Stroustrup/ProgrammingStroustrup/Programming

Page 19: Chapter 18 Vectors and  Arrays

Arrays don’t know their own sizeArrays don’t know their own sizevoid f(int pi[ ], int n, char pc[ ]) void f(int pi[ ], int n, char pc[ ])

// // equivalent toequivalent to void f(int* pi, int n, char* pc) void f(int* pi, int n, char* pc) // // warning: very dangerous code, for illustration only,warning: very dangerous code, for illustration only,// // nevernever “hope” that sizes will always be correct “hope” that sizes will always be correct

{{char buf1[200];char buf1[200];strcpy(buf1,pc);strcpy(buf1,pc); //// copy characters from copy characters from pcpc into into buf1buf1

//// strcpy terminates when a '\0' character is foundstrcpy terminates when a '\0' character is found//// hope that hope that pcpc holds less than 200 characters holds less than 200 characters

strncpy(buf1,pc,200);strncpy(buf1,pc,200); //// copy 200 characters from copy 200 characters from pcpc to to buf1buf1//// padded if necessary, but final '\0' not guaranteedpadded if necessary, but final '\0' not guaranteed

int buf2[300];int buf2[300]; //// you can’t say you can’t say char buf2[n]char buf2[n];; n n is a variable is a variableif (300 < n) error(if (300 < n) error(""not enough spacenot enough space""););for (int i=0; i<n; ++i) buf2[i] = pi[i];for (int i=0; i<n; ++i) buf2[i] = pi[i]; //// hope that hope that pipi really has space for really has space for

//// nn ints; it might have ints; it might have lessless

}}

1919Stroustrup/ProgrammingStroustrup/Programming

Page 20: Chapter 18 Vectors and  Arrays

Be careful with arrays and pointersBe careful with arrays and pointerschar* f()char* f(){{

char ch[20];char ch[20];char* p = &ch[90];char* p = &ch[90];// // ……*p = *p = ''aa'';; // // we don’t know what this’ll overwritewe don’t know what this’ll overwritechar* q;char* q; // // forgot to initializeforgot to initialize*q = *q = ''bb'';; // // we don’t know what this’ll overwritewe don’t know what this’ll overwritereturn &ch[10];return &ch[10]; // // oops:oops: ch ch disappear upon return fromdisappear upon return from f() f()

//// (an infamous “dangling pointer”)(an infamous “dangling pointer”)}}

void g()void g(){{

char* pp = f();char* pp = f();// // ……*pp = *pp = ''cc'';; // // we don’t know what this’ll overwritewe don’t know what this’ll overwrite

// // ((ff’s’s ch ch are gone for good after the return from are gone for good after the return from ff))}} 2020Stroustrup/ProgrammingStroustrup/Programming

Page 21: Chapter 18 Vectors and  Arrays

Why bother with arrays?Why bother with arrays? It’s all that C has It’s all that C has

In particular, C does not have vectorsIn particular, C does not have vectors There is a lot of C code “out there”There is a lot of C code “out there”

Here “a lot” means N*1B linesHere “a lot” means N*1B lines There is a lot of C++ code in C style “out there”There is a lot of C++ code in C style “out there”

Here “a lot” means N*100M linesHere “a lot” means N*100M lines You’ll eventually encounter code full of arrays and pointers You’ll eventually encounter code full of arrays and pointers

They represent primitive memory in C++ programsThey represent primitive memory in C++ programs We need them (mostly on free store allocated by We need them (mostly on free store allocated by newnew) to implement ) to implement

better container typesbetter container types Avoid arrays whenever you canAvoid arrays whenever you can

They are the largest single source of bugs in C and (unnecessarily) in They are the largest single source of bugs in C and (unnecessarily) in C++ programsC++ programs

They are among the largest sources of security violations (usually They are among the largest sources of security violations (usually (avoidable) buffer overflows)(avoidable) buffer overflows)

2121Stroustrup/ProgrammingStroustrup/Programming

Page 22: Chapter 18 Vectors and  Arrays

Types of memoryTypes of memoryvector glob(10);vector glob(10); // // globalglobal vector vector – “lives” forever– “lives” forever

vector* some_fct(int n)vector* some_fct(int n){{

vector v(n);vector v(n); // // local local vector vector – “lives” until the end of – “lives” until the end of scopescopevector* p = new vector(n); vector* p = new vector(n); // // free-store free-store vector – vector – “lives” until we“lives” until we delete delete itit// …// …return p;return p;

}}

void f()void f(){{

vector* pp = some_fct(17);vector* pp = some_fct(17);// // ……delete pp;delete pp; // // deallocate the free-store deallocate the free-store vectorvector allocated in allocated in some_fct()some_fct()

}} it’s easy to forget to delete free-store allocated objectsit’s easy to forget to delete free-store allocated objects

so avoid so avoid newnew//deletedelete when you can when you can 2222Stroustrup/ProgrammingStroustrup/Programming

Page 23: Chapter 18 Vectors and  Arrays

Initialization syntaxInitialization syntax(array’s one advantage over vector)(array’s one advantage over vector)

char ac[ ] = char ac[ ] = ""Hello, worldHello, world"";; // // array of 13 array of 13 charchars, not 12 (the compilers, not 12 (the compiler

// // counts them and then adds a null counts them and then adds a null

// // character at the endcharacter at the end

char* pc = char* pc = ""HowdyHowdy"";; // // pc pc points to an array ofpoints to an array of 6 6 charcharss

char* pp = {char* pp = {''HH'', , ''oo'', , ''ww'', , ''dd'', , ''yy'', 0 }; //, 0 }; // another way of saying the sameanother way of saying the same

int ai[ ] = { 1, 2, 3, 4, 5, 6 };int ai[ ] = { 1, 2, 3, 4, 5, 6 }; // // array of 6array of 6 ints ints

// // not 7 – the “add a null character at the end”not 7 – the “add a null character at the end”

//// rule is for literal character strings onlyrule is for literal character strings only

int ai2[100] = { 0,1,2,3,4,5,6,7,8,9 }; // int ai2[100] = { 0,1,2,3,4,5,6,7,8,9 }; // the last 90 elements are initialized to 0the last 90 elements are initialized to 0

double ad3[100] = { };double ad3[100] = { }; // // all elements initialized to 0.0all elements initialized to 0.0

2323Stroustrup/ProgrammingStroustrup/Programming

Page 24: Chapter 18 Vectors and  Arrays

Vector Vector (primitive access)(primitive access)// // a very simplifieda very simplified vector vector of of doubledoubless::

vector v(10);vector v(10);

for (int i=0; i<v.size(); ++i) {for (int i=0; i<v.size(); ++i) { // // pretty ugly:pretty ugly:

v.set(i,i);v.set(i,i);

cout << v.get(i);cout << v.get(i);

}}

for (int i=0; i<v.size(); ++i) {for (int i=0; i<v.size(); ++i) { // // we’re used to this:we’re used to this:

v[i]=i;v[i]=i;

cout << v[i];cout << v[i];

}}

2424

1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.00.0 9.010

Stroustrup/ProgrammingStroustrup/Programming

Page 25: Chapter 18 Vectors and  Arrays

Vector Vector (we could use pointers for access)(we could use pointers for access)// // a very simplifieda very simplified vector vector of of doubledoubles:s:class vector {class vector {

int sz;int sz; // // the sizethe sizedouble* elem;double* elem; // // pointer to elementspointer to elements

public:public:vector(int s) :sz(s), elem(new double[s]) { }vector(int s) :sz(s), elem(new double[s]) { } // // constructorconstructor// …// …double* operator[ ](int n) { return &elem[n]; } // double* operator[ ](int n) { return &elem[n]; } // access: return pointeraccess: return pointer

};};

vector v(10);vector v(10);for (int i=0; i<v.size(); ++i) {for (int i=0; i<v.size(); ++i) { // // works, but still too ugly:works, but still too ugly:

*v[i] = i;*v[i] = i; // // meansmeans *(v[i]), *(v[i]), that is return a pointer to that is return a pointer to //// the ithe ithth element, and dereference it element, and dereference it

cout << *v[i];cout << *v[i];}}

2525

1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.00.0 9.010

Stroustrup/ProgrammingStroustrup/Programming

Page 26: Chapter 18 Vectors and  Arrays

Vector Vector (we use references for access)(we use references for access)// // a very simplifieda very simplified vector vector of of doubledoubless::class vector {class vector {

int sz;int sz; // // the sizethe sizedouble* elem;double* elem; // // pointer to elementspointer to elements

public:public:vector(int s) :sz(s), elem(new double[s]) { }vector(int s) :sz(s), elem(new double[s]) { } // // constructorconstructor// …// …double& operator[ ](int n) { return elem[n]; } // double& operator[ ](int n) { return elem[n]; } // access: return referenceaccess: return reference

};};

vector v(10);vector v(10);for (int i=0; i<v.size(); ++i) {for (int i=0; i<v.size(); ++i) { // // works and looks right!works and looks right!

v[i] = i;v[i] = i; // // v[i] v[i] returns a reference to the ireturns a reference to the ithth element elementcout << v[i];cout << v[i];

}}

2626

1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.00.0 9.010

Stroustrup/ProgrammingStroustrup/Programming

Page 27: Chapter 18 Vectors and  Arrays

Pointer and referencePointer and reference You can think of a reference as an automatically dereferenced You can think of a reference as an automatically dereferenced

immutable pointer, or as an alternative name for an objectimmutable pointer, or as an alternative name for an object Assignment to a pointer changes the pointer’s valueAssignment to a pointer changes the pointer’s value Assignment to a reference changes the object referred toAssignment to a reference changes the object referred to You cannot make a reference refer to a different objectYou cannot make a reference refer to a different object

int a = 10;int a = 10;int* p = &a;int* p = &a; // // you need & to get a pointeryou need & to get a pointer*p = 7;*p = 7; // // assign to assign to aa through through pp

// // you need * (or [ ]) to get to what a pointer points toyou need * (or [ ]) to get to what a pointer points toint x1 = *p;int x1 = *p; // // read read aa through through pp

int& r = a; int& r = a; // // r is a synonym for r is a synonym for aar = 9;r = 9; // // assign to assign to aa through through rrint x2 = r;int x2 = r; // // read read aa through through rr

p = &x1;p = &x1; // // you can make a pointer point to a different objectyou can make a pointer point to a different objectr = &x1;r = &x1; // // error: you can’t change the value of a referenceerror: you can’t change the value of a reference

2727Stroustrup/ProgrammingStroustrup/Programming

Page 28: Chapter 18 Vectors and  Arrays

Next lectureNext lecture

We’ll see how we can change vector’s We’ll see how we can change vector’s implementation to better allow for changes in implementation to better allow for changes in the number of elements. Then we’ll modify the number of elements. Then we’ll modify vector to take elements of an arbitrary type vector to take elements of an arbitrary type and add range checking. That’ll imply looking and add range checking. That’ll imply looking at templates and revisiting exceptions.at templates and revisiting exceptions.

2828Stroustrup/ProgrammingStroustrup/Programming