17
E 332: C++ Pointers, Arrays and References Motivation and Overview • Often need to refer to another object – Without making a copy of the object itself • Two ways to do this – Indirectly, via a pointer • Gives the address of the object (analogy: street address) • Requires the code to do extra work: dereferencing • Like going to the given address, to talk to the person – Directly, via a reference • Acts as an alias for the object • Code interacts with reference as if it were object itself

Motivation and Overview

Embed Size (px)

DESCRIPTION

Motivation and Overview. Often need to refer to another object Without making a copy of the object itself Two ways to do this Indirectly, via a pointer Gives the address of the object (analogy: street address) Requires the code to do extra work: dereferencing - PowerPoint PPT Presentation

Citation preview

Page 1: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Motivation and Overview

• Often need to refer to another object– Without making a copy of the object itself

• Two ways to do this– Indirectly, via a pointer

• Gives the address of the object (analogy: street address)• Requires the code to do extra work: dereferencing• Like going to the given address, to talk to the person

– Directly, via a reference• Acts as an alias for the object• Code interacts with reference as if it were object itself

Page 2: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Review: What’s a Pointer?• A variable holding an address

– Of what it “points to” in memory

• Can be untyped– E.g., void * v; // points to anything

• However, usually they’re typed – Checked by compiler– Can only be assigned addresses of

variables of type to which it can point– E.g., int * p; // only points to int

• Can point to nothing– E.g., p = 0; // or p = nullptr; (C++11)

• Can change where it points– As long as pointer itself isn’t const – E.g., p = &i; // now points to i

0x7fffdad0

7

int i

int *p

Page 3: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Review: What’s a Reference?• Also a variable holding an address

– Of what it “refers to” in memory

• But with a nicer interface– A more direct alias for the object– Hides indirection from programmers

• Must be typed – Checked by compiler– Again can only refer to the type with

which it was declared– E.g., int & r =i; // refers to int i

• Always refers to (same) something– Must initialize to refer to a variable– Can’t change what it aliases

0x7fffdad0

7

int i

int & r

Page 4: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Untangling Operator Syntax

Symbol Used in a declaration

Used in a definition

unary & (ampersand)

reference, e.g.,int i; int &r = i;

address-of, e.g.,p = & i;

unary *

(star)

pointer, e.g., int * p;

dereference, e.g.,* p = 7;

-> (arrow) member access via pointer, e.g.,C c; C * cp=&c; cp->add(3);

. (dot) member access via reference or object, e.g., C c; c.add(3); C & cr = c; cr.add(3);

Page 5: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Aliasing and Pointers

int main (int argc, char *argv[]){ int i = 0; int j = 1; int * p = & i; int * q = & i; *q = 6; // i is now 6, j is still 1}

• Distinct variables have different memory locations– E.g., i and j

• A variable and all the pointers to it (when they’re dereferenced) all alias the same location– E.g., i, *p, and *q

• Assigning a new value to i, *p or *q changes value seen through the others

• But does not change value seen through j

0xefffdad06int i

int *p

1int j

0xefffdad0

int *q

Page 6: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Review: Const Pointers

int main (int argc, char **argv){ const int i = 0; int j = 1; int k = 2;

// pointer to int int * w = & j; // (array names are like const // pointers to their 0th position) // const pointer to int int * const x = & j; // pointer to const int const int * y = & i;

// const pointer to const int const int * const z = & j;}

• Read declarations right to left• Make promises via the const keyword

in pointer declaration:– not to change where the pointer

points– not to change value at the location to

which it points• Can (only) change

– Where w points and the value at the location to which it points

– The value at the location to which x points

– Where y points• A pointer to non-const cannot point to a

const variable– neither w nor x can point to i– any of them can point to j

Page 7: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Pointers and Arraysint main (int argc, char **argv){ int arr [3] = {0, 1, 2};

int * p = & arr[0]; int * q = arr; // p, q, arr point to same place }

• An array holds a contiguous sequence of memory locations– Can refer to locations using either

array index or pointer notation– E.g., *arr vs. arr[0]– E.g., *(arr+1) vs. arr[1]

• Array variable essentially behaves like a const pointer– Like int * const arr;– Can’t change where it points– Can change locations unless

declared array-of-const– E.g., const int arr[3];

• Can initialize other pointers to the start of the array– Using array name, or using

address of 0th element

0xefffdad0

2int arr [3]

int *p

1

0xefffdad0int *q

0

Page 8: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Pointer Arithmetic With Arrays

int main (int argc, char **argv){ int arr [3] = {0, 1, 2};

int * p = & arr[0]; int * q = arr; // p, q now point to same place ++q; // now q points to arr[1]}

• Adding or subtracting int n moves a pointer by n of the type to which it points– I.e., by n array positions– E.g., value in q is increased

by sizeof(int) by ++q• Can move either direction

– E.g., --q, ++p• Can jump to a location

– E.g., p+=2, q-=1• Remember that C++ (only)

guarantees that sizeof(char)==1– But compiler figures out

other sizes for you

0xefffdad0

2int arr [3]

int *p

1

0xefffdad0int *q

0

Page 9: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Arrays of (and Pointers to) Pointers

int main (int argc, char *argv[]){ // could declare char **argv for (int i = 0; i < argc; ++i)

cout << argv[i] << endl;

}

• Can have pointers to pointers• Can also have an array of

pointers (like a const pointer to a pointer type)

• E.g., argv parameter in main– Array of pointers to character

strings– Could also declare as a

pointer to the first pointer– Notice array dimension is not

specified– Instead a special argument

(argc) holds array size• By convention, character

strings are zero terminated– Special char is ‘\0’ not ‘0’

0xefffaad0

char * argv[]

int argc 2

0xefffa0d0

h e l l o

t e s t \0

\0

Page 10: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Rules for Pointer Arithmetic

int main (int argc, char **argv){ int arr [3] = {0, 1, 2};

int * p = & arr[0]; int * q = p + 1;

return 0;}

• You can subtract (but not add, multiply, etc.) pointers– Gives an integer with the

distance between them

• You can add/subtract an integer to/from a pointer– E.g., p+(q-p)/2 is allowed

but (p+q)/2 gives an error

• Note relationship between array and pointer arithmetic – Given pointer p and integer n, the expressions p[n] and *(p+n) are both allowed and mean the same thing

0xefffdad0

2int arr [3]

int *p

1

0xefffdad0int *q

0

Page 11: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Watch out for Pointer Arithmetic Errors

int main (int argc, char **argv){ int arr [3] = {0, 1, 2};

int * p = & arr[0]; int * q = arr; // p, q now point to same place int n; q+=n; // now where does q point?}

• Dereferencing a 0 pointer will crash your program

• Accessing memory location outside your program can– Crash your program– Let you read arbitrary values– Let you modify that location– Last two: hardest to debug

• Watch out for– Uninitialized pointers– Failing to check pointer for 0– Adding or subtracting an

uninitialized variable to a pointer

– Errors in loop initialization, termination, or increment

0xefffdad0

2int arr [3]

int *p

1

0xefffdad0int *q

0

Page 12: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Arrays, Pointers, and Dynamic Allocation

Foo * baz (){ // note the array form of new int * const a = new int [3]; a[0] = 0; a[1] = 1; a[2] = 2; Foo *f = new Foo; f->reset(a); return f;}

void Foo::reset(int * array) { // ctor must initialize to 0 delete [] this->array_ptr; this->array_ptr = array;}

void Foo::~Foo() { // note the array form of delete delete [] this->array_ptr;}

• We’ve talked mainly about stack variables so far

• Arrays, like individual objects, can be allocated (new) and de-allocated (delete) dynamically – more details in later lectures

• Arrays have a particular syntax – with [ ] in the new and delete

calls– Ensures constructors and

destructors of elements are called automatically

• Don’t leak, destroy safely– Requires careful attention to

details of memory management– More about this in next lectures

Page 13: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Aliasing and References

int main (int argc, char **argv){ int i = 0; int j = 1; int & r = i; int & s = i; r = 8; // i is now 8, j is still 1}

• An object and all the references to it alias the same location– E.g., i, r, and s

• Assigning a new value to i, r or s changes value seen through the others

• But does not change value seen through j

0xefffdad08int i

int & r

1int j

0xefffdad0

int & s

Page 14: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

References to Const

int main (int argc, char **argv){ const int i = 0; int j = 1; int & r = j; // r can’t refer to i const int & s = i; // ok for s,t const int & t = j; // to alias i,j}

• Remember: references must refer to something– Can’t be nil

• Also, once initialized, they cannot be changed– E.g., can’t redirect t to i

• Const with a reference – A promise not to change

what’s aliased– E.g., can’t use t to change j

• Can’t use reference to non-const with a const variable, but reverse is ok

Page 15: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Review: Parameter Passing

int main (int argc, char **argv){ int h = -1; int i = 0; int j = 1; int k = 2; return func (h, i, j, & k);}

int func (int a, const int & b, int & c, int * d){ ++a; c = b; *d = c ++d;

return 0;}

• By value– Makes a copy i.e., of h into

local variable a– ++a does not change h

• By reference– Alias for passed variable– c = b changes j– can’t change b (or i): const

• Can pass address by value– And then use address value

to change what it points to– *d = c changes k– ++d changes local pointer

Page 16: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

References to Pointers

int main (int argc, char **argv){ int j = 1; int & r = j; // r aliases j int * p = & r; // p really // points to j int * & t = p; // t aliases p}

• Can’t have a pointer to a reference– But can point to what the

reference aliases

• Address-of operator on a reference to a variable– Gives address of variable– … not of reference itself

• Reference to a pointer– An alias for the pointer … not for what it points to– Useful to pass a pointer to

code that may change it

0xefffdad01int j

int & r

int * p0xefffdad0

0xefffdad0

int * & t

Page 17: Motivation and Overview

CSE 332: C++ Pointers, Arrays and References

Why to Use STL Vectors Instead of C++ Arrays• Vectors do a lot of (often tricky)

memory management for you– Use new[] and delete[] internally– Resize memory as needed– Don’t leak memory

• Easier to pass to functions– E.g., can tell you their size– Don’t have to pass a separate

size variable– Don’t need a pointer by reference

in order to resize

• Still have to pay some attention – E.g., push_back can allocate

more memory but operator [] can’t– E.g., vectors copy and take

ownership of objects they contain

#include <iostream>

#include <vector>

using namespace std;

int main (int, char *[]) {

vector<int> v;

// This would be asking for trouble....

// v[0] = 1; v[1] = 2; v[2] = 4;

// ... but this works fine...

v.push_back (1);

v.push_back (2);

v.push_back (4);

// ... and now this is ok ...

for (size_t s = 0; s < v.size(); ++s) {

cout << "v[" << s << "] is "

<< v[s] << endl;

}

return 0;

}