Académique Documents
Professionnel Documents
Culture Documents
CS 1037a Topic 2
Overview:
part I
Overview:
part II
2-3
Overview:
part III
Related materials
from Main and Savitch Data Structures & other objects using C++
Sec. 4.1: pointers and dynamic memory Sec. 4.2: pointers and arrays as parameters
from CS1037 labs
Part I
POINTERS
2-6
Background info
all data (variables/objects/arrays) processed by computer program sit in computer memory computer memory can be seen as a HUGE one-dimensional array
For example, can assume that each cell
0
1 2 3 4 5 6 7 8 9 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
each cell in this memory array has a unique index, normally referred to as address
2-7
Background info
When a function (e.g. main) starts to run, operating system (OS) allocates/assigns memory space to all declared variables, objects or arrays declared in this function
Assume, for simplicity, that each cell
0
1 2 3 4 5 6 7 8 9 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
char a;
int j;
char arr[6];
Point p;
2-8
Background info
Values of variables/objects in the memory can be accessed (for example) using indexes (addresses) of the corresponding cells in the memory, if known
Assume, for simplicity, that each cell
0
1 2 3 4 5 6 7 8 9 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
char a;
byte #12
int j;
bytes #20-23
char arr[6];
bytes #30-35
Point p;
bytes #37-44
2-9
Background info
Since variables/objects/arrays occupy consecutive cells in the memory, it is enough to know address of the first cell as long as we know the size of object/array
Assume, for simplicity, that each cell
0
1 2 3 4 5 6 7 8 9 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
char a;
byte #12
int j;
4 bytes after #20
char arr[6];
6 bytes after #30
Point p;
8 bytes after #37
2-10
12 20 34 37
1 2 3 4 5 6 7 8 9 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
char a;
int j;
char arr[6];
Point p;
2-11
Pointers
Known location (address) of an object in the memory could be effectively used in coding
- e.g. passing address of a large object as function argument - more later
- Q: How can we store and manipulate objects addresses when coding - A: Use pointer variables (or simply pointers)
declaring pointer variables
Pointers
Pointer is a basic variable type very similar to integers value of any variable of pointer type is ONLY a memory address !!!
- that is, integer (in hexadecimal format)
0 1 2 3 4 5 6 7 8 9 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
char a;
int j;
char arr[6];
Point p;
Question:
Pointers
Like other types of variables/objects, pointer variables occupy some space in memory
1 2 3 4 5 6 7 8 9 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
char a; int* t;
int j;
char arr[6];
Point p;
2-14
Pointers
Like other types of variables/objects, pointer variables occupy some space in memory
regardless of exact type (int*, char*, Point*, ) any pointer occupies the same amount of space
- e.g. 4 bytes in 32 bit Windows PCs (8 bytes in 64 bit Windows)
0 1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-15
Pointers
EXAMPLE:
s = &a; t = &j;
// value of pointer s is now 12 // value of pointer t is now 20 // but since t is a pointer to int, compiler knows that t points at // a chunk of 4 consecutive bytes 20-23 (with an int object) // value of pointer g is now 37 // but since g is a pointer to Point, compiler knows that g points at // a chunk of 8 consecutive bytes 37-44 (with a Point object)
g = &p;
1 2 3 4 5 6 7 8 9 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
12
20
37
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-16
Pointers
EXAMPLE:
s = &a; t = &j;
// value of pointer s is now 12 // value of pointer t is now 20 // but since t is a pointer to int, compiler knows that t points at // a chunk of 4 consecutive bytes 20-23 (with an int object) // value of pointer g is now 37 // but since g is a pointer to Point, compiler knows that g points at // a chunk of 8 consecutive bytes 37-44 (with a Point object)
g = &p;
1 2 3 4 5 6 7 8 9 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
char* s;
address of a chunk of memory for one char
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
address of a 2-17 chunk of memory for one Point
Pointers
Despite some similarity, pointer types have to be specialized for each class of objects
- to avoid mixing addresses of different types of objects
in order to properly access objects data from a given memory address, OS must know how many consecutive bytes to read and how to interpret them. Compiler obtains this information in operations with pointers from their specific type.
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-18
Pointers
EXAMPLE:
s = &a; // value of pointer s is now 12 (address determined by operator &) t = &j; // value of pointer t is now 20 w = &k; // value of pointer w is now 37
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
int* w;
2-19
Pointers
EXAMPLE:
s = &a; // value of pointer s is now 12 (address determined by operator &) t = &j; // value of pointer t is now 20 w = &k; // value of pointer w is now 37 t = w; // value of pointer t is now 37 (copied from value of pointer w)
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
int* w;
2-20
Pointers
EXAMPLE:
s = &a; // value of pointer s is now 12 (address determined by operator &) t = &j; // value of pointer t is now 20 w = &k; // value of pointer w is now 37 t = w; // value of pointer t is now 37 (copied from value of pointer w) w = &j;
// value of pointer w is now 20 (address determined by operator &)
char* s;
char a; int* t;
int j;
int* w;
2-21
- copies (address) value evaluated in expression on the right hand side - pointer and expression on the r.h.s. should have the same type
char a, h, *c; // a way to declare pointer to char variable c char *s = &a; // as other types, pointers can be initialized at declaration c = &h; // operator & returns value of type char* (pointer to char) s = c;
EXAMPLE
int j, *w, *t; // a way to declare multiple pointers t = &j; // here, operator & returns value of type int* (pointer to int) s = t; NOTE: all pointers, e.g. s and t, have very similar c = &j;
looking integer values. Yet, compiler treats char* and int * variables as different types
Dereference Operator
Accessing (reading) data in memory
by variable/object name
int i = 5; // one integer object (4 bytes) is allocated
// in memory and its value is initialized to 5;
cout << i;
// value of i is extracted
2-23
Dereference Operator
Accessing (reading) data in memory
by memory address
int i = 5; // one integer object (4 bytes) is allocated
// in memory and its value is initialized to 5; int *t = &i; // one pointer (4 bytes) is allocated in memory and // initialized with address determined by operator & cout << *t; // address stored in t is extracted and // integer value (4 bytes) is read from // the corresponding location in the memory
Dereference operator *() tell the program to read data from address specified by expression on the right. (the known pointer-type
for expression on the right tells compiler how to read memory.)
2-24
Dereference Operator
Avoid confusion!
int a, *r; int *t = &a;
int j = *t; *t = a; in-front of expression containing previously declared pointer variables, symbol * indicates dereference operator
2-25
symbol * indicates pointer variable type in-front of any new variable name (inside declaration)
Pointers to Objects
Accessing objects in memory
by variable/object name
Point p(4,9);
p.shift_by(2,7); // shifts coordinates of a point by a vector cout << p.x; // value of x coordinate is extracted
2-26
Pointers to Objects
Accessing objects in memory
by memory address
Point p(4,9); Point *g = &p;
(*g).shift_by(2,7); // shifts coordinates of a point by a vector cout << (*g).x; // value of x coordinate is extracted
2-27
Pointers to Objects
Convenient syntax
- assume that value of expression a is objects address: e.g. Object * a = &object;
Pointers to Objects
Point p(4,9); Point *g = &p; g->shift_by(2,7); cout << g->x; Point p(4,9); Point *g = &p; (*g).shift_by(2,7); cout << (*g).x;
Pointer Arithmetic
s = &a; // 12 t = &j; // 20 g = &p; // 37
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-30
Pointer Arithmetic
s = &a; // 12 t = &j; // 20 g = &p; // 37 s = (s+1); t = (t+1); g = (g+1);
45: address of the next Point
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-31
Pointer Arithmetic
s = &a; // 12 t = &j; // 20 g = &p; // 37 s = (s-3); t = (t+2); g = (g+1);
45 = 37+1*sizeof(Point)
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-32
Pointer Arithmetic
s = &a; // 12 t = &j; // 20 g = &p; // 37 s -= 3; t += 2; g++;
45 = 37+1*sizeof(Point)
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-33
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-34
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-35
arr[2]=q;
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-36
s = arr; // is perfectly fine, copies address 30 from arr s[2] = q; syntax allowed for pointers too!!!
0
arr[2]=q;
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-37
e.g.
s[2] = q;
*(s+2)=q;
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-38
arr[2] = q;
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-39
1 2 3 4 5 6 7 8 9 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
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
2-40
char* s;
char a; int* t;
int j;
char arr[6];
Point p; Point* g;
a very
int *s;
int *s = NULL;
..... .. s = &h;
.. ...... s = &h;
2-43
a[0]=(3,7)
a[1]=(0,0)
a[2]=(-2,0)
1 2 3 4 5 6 7 8 9 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
Point a[3];
2-44
Point *p; p = a;
// is perfectly fine
a[0]=(3,7) a[1]=(0,0) a[2]=(-2,0)
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-45
a[0]=(3,7)
a[1]=(1,4)
a[2]=(-2,9)
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-46
a[0]=(3,7)
a[1]=(1,4)
a[2]=(-2,9)
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-47
a[0]=(3,7)
a[1]=(1,4)
a[2]=(-2,9)
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-48
Syntax alert
(*(p+1)).shift_by(1,4); (*(p+2)).y = 9;
(p+1)->shift_by(1,4); (p+2)->y = 9;
p[1].shift_by(1,4); p[2].y = 9;
-5 ?
0
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-50
-5
0
1 2 3 4 5 6 7 8 9 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
Point* p;
Point a[3];
2-51
Formal argument of negate (pointer x) is initialized from the This call-by-reference syntax actual argument: value of only hides the use of memory expression &b. Such call-by-value addresses (pointer values), for pointer x allows negate to made explicit on the right modify value of variable2-52 b.
In this course, we will explicitly use pointers as function arguments in order to emphasize 2-53 understanding of memory access operations
Part II
2-55
Practical applications that can be coded using ONLY static variables is very limited (mostly toy examples)!
2-56
The number of image objects that will be allocated in your computers memory is not known when the browsers code is compiled. How would Firefox or Microsoft know?!
157
void Slide::onMouseDrag(Point start, Point end) { if (theArrowButton.isSelected()) { ArrowShape* arrow = new ArrowShape(start,end); m_shapes.add(arrow); } if (theCircleButton.isSelected()) { ...etc... } }
Statically allocated Point Point c; Point *p = NULL; if (yes) p = get_random_point(); .... if (p!=NULL) delete p; .... 2-59 Releasing memory of dynamic Point
- created dynamic objects sit in memory until explicitly deleted by operator delete
2-60
int j;
4
Point a[3];
(0,0) (0,0)
call stack
(0,0)
heap
(1,4) 3
static objects
dynamic objects
2-64
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 1
int a=10, b=3; int * s; s = &a;
call stack
heap
10 a
3
b
2-65
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 1
int a=10, b=3; int * s; s = &a; s = new int;
call stack
heap
10 a
3 s b
2-66
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 1
int a=10, b=3; int * s; s = &a; s = new int; *s = 6;
call stack
heap
10 a
3 s b
2-67
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3);
call stack s
heap
(1,3)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5;
call stack s
heap
(1,5)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5; s = b-1;
call stack s
heap
(1,5)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5; s = b-1; *(s+2) = Point(7,9);
call stack s
heap
(1,5)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5; s = b-1; *(s+2) = Point(7,9); (s+1)->shift_by(2,4);
call stack s
heap
(1,5)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5; s = b-1; *(s+2) = Point(7,9); (s+1)->shift_by(2,4); s[1].shift_by(1,1);
call stack s
heap
(1,5)
Memory Diagrams
Through out the course, we will use simplified memory diagrams illustrating the state of variables/objects and pointers in the memory after executing given code
Example 2
Point b[3]; Point *s = new Point(1,3); s->y = 5; s = b-1; *(s+2) = Point(7,9); (s+1)->shift_by(2,4); s[1].shift_by(1,1); s[3] = Point(8,6);
call stack s
heap
(1,5)
call stack
heap
(2,3)
(0,0)
NULL
(4,5)
2-75
call stack
heap (2,3)
(0,0)
NULL
(4,5)
2-76
call stack
heap (2,3)
(0,0)
NULL NULL
(4,5)
2-77
call stack
heap
(2,3)
(0,0)
NULL
(5,6)
2-78
Syntax Alert
Pointers and arrays of objects
(slides 43-50) Point a[3]; Point *p; p = a; . . p[1].shift_by(1,4); p[2].y = 9; p[2]->y = 2;
Correct syntax (a.member or a->member) always depends on the type of expression a (is it Obj or a pointer Obj*?)
Syntax Alert
Pointers and arrays of objects
(slides 43-50) Point a[3]; Point *p; p = a; . . p[1].shift_by(1,4); p[2].y = 9; p[2]->y = 2; (p+2)->y = 2; // is OK
Correct syntax (a.member or a->member) always depends on the type of expression a (is it Obj or a pointer Obj*?)
Example 2
Card * c = new Card(); .... ..... c->~Card(); // WRONG
Correct version
Card * c = new Card(); .... ..... ?
call stack
heap (H,6)
2-81
Example 2
Card * c = new Card(); .... ..... c->~Card(); // WRONG
Correct version
Card * c = new Card(); .... ..... delete c; // GOOD
call stack
heap (H,6)
Example 2
Card * c = new Card(); .... ..... c->~Card(); // WRONG
Correct version
Card * c = new Card(); .... ..... delete c; // GOOD c = NULL; // GOOD
call stack
NULL
heap (H,6)
call stack
heap
(H,6)
2-84
call stack
NULL
heap
(H,6)
MEMORY LEAK: dynamic object still occupies memory but NONE of the pointers keeps its address 2-85
call stack
NULL
heap
(H,6)
MEMORY LEAK: dynamic object still occupies memory but NONE of the pointers keeps its address 2-86
- the size of static arrays is fixed (each time you compile your program), it can not change at run time. Point c[k];
2-87
188
Statically allocated array Point c[4]; Point *p = NULL; if (k>0) p = get_array(k); .... if (p!=NULL) delete [ ] p; .... 2-89 Releasing memory of dynamic array
int j;
4
Point a[3];
(0,0) (0,0)
call stack
(0,0)
heap
(1,4)
static objects
dynamic object
2-90
int j;
4
call stack
heap
(1,4) (0,0) (0,0) (0,0)
static objects
dynamic object
void func(int k) { ..... Point c[5]; Point *p = new Point [k]; .... Size of dynamic array may vary } at different run-times depending 2-92 on arguments value
void func(int k) { ..... Point c[k]; Point *p = new Point [k]; .... Size of dynamic array may vary } at different run-times depending 2-93 on arguments value
- created dynamic array of objects sits in memory until explicitly deleted by operator delete [ ] 2-94
2-95
2-96
2-97
Part III
call stack
heap
call stack
heap c a t
2-99
c
a
t a
3
DynArray a(3); // hides dynamic memory allocation a[0]=c; a[1]=a; a[2] =t; // works like a.m_container[2]=t;
call stack c
heap a t
2-100
call stack a
NULL
heap (1,2)
call stack
(7,4)
2-101
call stack a
NULL
heap (1,2)
call stack
(7,4)
2-102
call stack a
NULL
heap (1,2)
call stack
(7,4)
2-103
call stack a
NULL NULL
heap (1,2)
call stack
NULL
(7,4)
2-104
?
Point *a[3]; a[1] = new Point(3,5); Point **a = new Point*[3]; a[0] = new Point(1,2);
call stack a
heap (1,2)
call stack
heap
(3,5) (7,4)
a
(1,2) (3,5)
(7,4)
2-105
Double Pointers
A pointer can also store address of other pointer variables
-a
is a pointer to pointer
(a.k.a. double pointer)
equivalent code Point **a = new Point*[3]; a[0] = new Point(1,2);
a[2]->x = 7; a[0]->shift_by(1,2);
*(a[2]).x = 7; *(a[0]).shift_by(1,2);
call stack
heap
a
(1,2) (3,5)
*(*(a+2)).x = 7; *(*a).shift_by(1,2);
(7,4)
2-106
Double Pointers
call stack
Point **a; //declaration
heap
2-107
Double Pointers
call stack
Point **a; //declaration a = new Point *;
heap
2-108
Double Pointers
call stack
Point **a; //declaration a = new Point *; *a = new Point(3,4);
heap
(3,4)
2-109
Double Pointers
call stack
Point **a; //declaration a = new Point *; *a = new Point(3,4); .... delete *a;
heap
(3,4)
2-110
Double Pointers
call stack
Point **a; //declaration a = new Point *; *a = new Point(3,4); .... delete *a; delete a;
heap
(3,4)
2-111
Double Pointers
call stack
Point **a; //declaration a = new Point *; *a = new Point(3,4); .... delete *a; delete a; a = NULL;
heap
NULL
(3,4)
2-112
call stack
Point **a; //declaration
heap
2-113
call stack
Point **a; //declaration a = new Point* [3];
heap
?
2-114
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2];
heap
(0,0) (0,0)
(0,0) (0,0)
a
(0,0) (0,0)
2-115
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2]; a[2][1].x = 5;
heap
(0,0) (0,0)
(0,0) (0,0)
a
(0,0) (5,0)
2-116
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2]; a[2][1].x = 5; a[1][0].shift_by(2,3);
heap
(0,0) (0,0)
(2,3) (0,0)
a
(0,0) (5,0)
2-117
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2]; a[2][1].x = 5; a[1][0].shift_by(2,3); a[0][1] = Point(6,9);
heap
(0,0) (6,9)
(2,3) (0,0)
a
(0,0) (5,0)
2-118
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2]; a[2][1].x = 5; a[1][0].shift_by(2,3); a[0][1] = Point(6,9);
heap
(0,0) (6,9)
(2,3) (0,0)
a
(0,0) (5,0)
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2]; a[2][1].x = 5; a[1][0].shift_by(2,3); a[0][1] = Point(6,9);
heap
(0,0) (6,9)
(2,3) (0,0)
a
(0,0) (5,0)
call stack
Point **a; //declaration a = new Point* [3]; for (int i=0; i<3; i++) a[i] = new Point[2];
NULL
heap
allocation
(0,0) (6,9)
(2,3) (0,0) (0,0) (5,0)
deallocation
use
2-121
Point **a;
//declaration
heap
call stack
?
a
2-122
heap
call stack
?
2-123
heap
call stack
?
2-124
Point **a; //declaration a = new Point* [3]; a[0] = new Point[6]; for (int i=1; i<3; i++) a[i] = a[i-1]+2;
heap
call stack
a[0]
a[1]
a[2]
2-125
Point **a; //declaration a = new Point* [3]; a[0] = new Point[6]; for (int i=1; i<3; i++) a[i] = a[i-1]+2;
heap
a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1]
call stack
a[0]
a[1]
a[2]
2-126
Point **a; //declaration a = new Point* [3]; a[0] = new Point[6]; for (int i=1; i<3; i++) a[i] = a[i-1]+2;
heap
call stack
a[0]
a[1]
a[2]
2-127
Point **a; //declaration a = new Point* [3]; a[0] = new Point[6]; for (int i=1; i<3; i++) a[i] = a[i-1]+2;
heap
call stack
a
2-128
Point **a; //declaration a = new Point* [3]; a[0] = new Point[6]; for (int i=1; i<3; i++) a[i] = a[i-1]+2;
heap
allocation
use
call stack
NULL
deallocation
heap
Question:
Is it possible to avoid one extra array storing addresses of columns?
a[0][0]
a[0][1]
a[1][0]
a[1][1]
a[2][0]
a[2][1]
call stack
a[0]
a[1]
a[2]
2-130
class Table2D {
Table2D::Table2D(int w, int h) { m_width = w; m_height = h; m_data = new float[w*h]; for (int i=0; i<w*h; i++) m_data[i]=0; }
Table2D::~Table2D() { delete [ ] m_data; }
returns address of the x-th column
float * Table2D::operator[ ] (int x) { return m_data + x*m_height; } computed using pointer arithmetic
main() { Table2D a(3,2); // declaration ... ... constructor allocates memory in the heap
heap
call stack
Table2D::Table2D(int w, int h) { m_width = w; m_height = h; m_data = new float[w*h]; for (int i=0; i<w*h; i++) m_data[i]=0; }
3
a
2
2-132
heap
0
NOTE: (a[x]) [y] = *(a[x] +y )
applying standard operator [ ] (see p. 2-38) to a pointer returned by overloaded operator [ ] for object a
7.1
call stack
a[2]
m_data+2*m_height
3
a
2
2-133
heap
column 0
column 1
column 2
0
NOTE: (a[x]) [y] = *(a[x] +y )
applying standard operator [ ] (see p. 2-38) to a pointer returned by overloaded operator [ ] for object a
7.1
call stack
3
a
2
2-134
a[2]
m_data+2*m_height
address of column 2
heap
column 0
a[0][0] a[0][1]
column 1
a[1][0] a[1][1]
column 2
a[2][0] a[2][1]
0
NOTE: (a[x]) [y] = *(a[x] +y )
applying standard operator [ ] (see p. 2-38) to a pointer returned by overloaded operator [ ] for object a
7.1
call stack
3
a
2
2-135
heap
column 0
a[0][0] a[0][1]
column 1
a[1][0] a[1][1]
column 2
a[2][0] a[2][1]
7.1
call stack
3
a
2
2-136
heap
7.1
Table2D::~Table2D() { delete [ ] m_data; } This code is run just before object a is removed from the memory (in call stack)
call stack
3
a
2
2-137
Image::Image(int w, int h) { m_width = w; m_height = h; m_pixels = new int[w*h*3]; //RGB } Image::~Image() { delete [ ] m_pixels; }
2-138