Show Lecture.Pointers as a slide show.
int a[] = {11, 22, 33, 44, 55}; int *p = &a[2]; cout << *p << '\n'; p += 2; cout << *p << '\n';
33 55
a
is an array of int
s
a[2]
is an int
&a[2]
is an int *
, or the address of an int
p
is an int *
, or a pointer to an int
*p
is an int
int a[] = {11, 22, 33, 44, 55}; int *p = &a[2], n; n = p; p = n;
c.cc:3: error: invalid conversion from 'int*' to 'int'
These are all equivalent, since spaces matter little:
int *a; int* b; int*c; int * d;
However, consider this. What types are e
and f
?
int* e, f;
That’s why I do this:
int *g, h;
int a[] = {11, 22, 33, 44, 55}; int *p = a; cout << *p << '\n'; *p += 8; cout << *p << '\n'; p += 2; cout << *p << '\n';
11 19 33
a
is an array of int
s
a
is equivalent to &a[0]
nullptr
: modern C++ way to do it
NULL
: old-fashioned C way to do it
0
: how the implementation actually works. Do not do this.
int xyz, *p = &xyz; if (p) cout << "Hello\n";
Hello
int *p = nullptr;
A reference is like a pointer, with auto-indirection.
int a[] = {11, 22, 33, 44, 55}; int &r = a[2]; cout << r << '\n'; r += 2; cout << r << '\n';
33 35
void f1(string s) { // call by value cout << s << '\n'; } void f2(const string &s) { // call by const reference cout << s << '\n'; } int main() { string filename = "/etc/group"; f1(filename); f2(filename); return 0; }
/etc/group /etc/group
const
so that f2
can’t change the argument.
const
Declaration | Explanation |
---|---|
int *a | non-const pointer to non-const int s |
const int *b | non-const pointer to const int s |
int *const c | const pointer to non-const int s |
const int *const d | const pointer to const int s |
int &e = … | reference a non-const int |
const int &f = … | reference to a const int |
Declare a pointer to constant integers. We can change the pointer, but not the integers.
int alpha[] = {11,22,33,44,55}; const int *p = alpha; p += 2; cout << *p;
33
int beta[] = {11,22,33,44,55}; const int *p = beta; *p = 42;
c.cc:3: error: assignment of read-only location '* p'
Declare a constant pointer to integers. We can change the the integers, but not the pointer.
int gamma[] = {11,22,33,44,55}; int *const p = gamma; *p = 42; cout << *p;
42
int delta[] = {11,22,33,44,55}; int *const p = delta; p++;
c.cc:3: error: increment of read-only variable 'p'
a->b()
, or a.b()
?
a
is a pointer to an object, use: a->b()
a
is an object, use: a.b()
a
is a reference, then it’s an alias for something--use the
rules for whatever it refers to.
->
for objects—we’ll learn about that later.
vector<bool> v(42, true); // v is a vector of bool cout << v.size() << '\n';
42
Here, we use a dot, because v
is an object, not a pointer.
vector<bool> v(42, true); // v is a vector of bool vector<bool> *p = &v; // p is a pointer to vector of bool cout << (*p).size() << '\n' << p->size() << '\n';
42 42
Two ways (one ugly, one not) of doing the same thing.
vector<bool> v(42, true); // v is a vector of bool vector<bool> &r = v; // r is a reference to a vector of bool cout << r.size() << '\n';
42
r
is a reference to an object.
r
.
The name of an array is equivalent to a pointer to its first element.
Write the data via the first pointer, and read it from the second pointer.
double alpha[20]; double *a = alpha; double *b = &alpha[0]; *a = 123.456; cout << *b << '\n'; if (a == b) cout << "Pointers are equal.\n";
123.456 Pointers are equal.
You can think of there being two sorts of arrays.
The array alpha
is on the stack.
int alpha[10]; for (int i=0; i<10; i++) alpha[i] = i*i; for (int i=0; i<10; i++) cout << alpha[i] << ' '; cout << '\n'; cout << "size of alpha: " << sizeof(alpha) << '\n';
0 1 4 9 16 25 36 49 64 81 size of alpha: 40
The pointer beta
is on the stack,
pointing to ten int
s of dynamic memory.
int *beta = new int[10]; for (int i=0; i<10; i++) beta[i] = i*i; for (int i=0; i<10; i++) cout << beta[i] << ' '; cout << '\n'; cout << "size of beta: " << sizeof(beta) << '\n'; delete[] beta;
0 1 4 9 16 25 36 49 64 81 size of beta: 8
const char a[] = "abcdefghijklm"; const char *b = "nopqrstuvwxyz"; cout << a << ' ' << b << '\n' << sizeof(a) << ' ' << sizeof(b) << '\n';
abcdefghijklm nopqrstuvwxyz 14 8
p++
, or ++p
, or p+=1
, or p=p+1
do?
int *
or
string *
, and not just *
.
int data[] = {11,22,33,44,55,66,77,88,99}; int *p = data; // p points to 11 p += 3; // p now points to 44 cout << *p << '\n';
44
Let’s look at the pointers:
int data[] = {11,22,33,44,55,66,77,88,99}; int *p = data; cout << p << '\n'; p += 3; cout << p << '\n';
0x7ffe94103060 0x7ffe9410306c
Similarly, subtracting pointers yields the number of items, not the number of bytes.
int data[] = {11,22,33,44,55,66,77,88,99}; int *p = data+7; // p points to 88 p--; // p now points to 77 cout << *p << '\n';
77
No, the other kind of pointer subtraction:
int data[20]; int *a = &data[2], *b = &data[9]; cout << b-a << '\n'; // b is 7 past a
7
Of course, you can have a pointer to any type.
// pointer to pointer to int: int **p; // pointer to pointer to pointer to pointer to pointer to int int *****q; // one hundred pointers to ints: int *a[100]; // pointer to a function that takes a float & a bool and returns an int double (*fn)(float, bool);