Upload
dora-doyle
View
19
Download
2
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
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
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
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
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);
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
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
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
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
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
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
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
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
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
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
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
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
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;
}