int *ip;
This does not initialize the pointer.
int i;
ip = &i;
*ip = *ip + 3;
In general, * and & are inverses.
int *p;
{
int i = 5;
p = &i;
} // i ceases to exist
*p = 3; // undefined behaviour
int *ip = 0;
cf. null in Java.
const int *p;
Means that things pointed to by p cannot be changed through p
(but p itself can be changed.)
It is possible to have pointers to pointers:
int i;
int *p1 = &i;
int **p2 = &p1;
int ***p3 = &p2;
and these may be qualified with const in various ways.
class Point {
public:
int x, y;
Point (int xx, int yy) : x(xx), y(yy) {}
};
We can refer to fields as follows:
Point my_point(2, 3);
Point *p = &my_point;
cout << (*p).x << '\n';
or equivalently as
cout << p->x << '\n';
and similarly for member functions.
We have already used vectors, but C++ also has arrays, which are fixed in size:
int arr[40];
for (int i = 0; i < 40; i++)
arr[i] = arr[i] + 5;
Unlike Java, there is no check that the index is in bounds.
Advice: use vectors instead unless the collection has a definite, fixed size.
int arr[40];
int *p = arr;
Now *p is equivalent to arr[0],
and indeed to *arr.
The following are all equivalent:
arr[0] = arr[0] + 5;
*p = *p + 5;
*arr = *arr + 5;
int arr[40];
can be passed as a pointer parameter:
void f(int *p) { ... }
A function that really takes a pointer to a single element looks the same.
(This is less common in C++ than in C, which has no references.)
'\0' character.
char name[] = "Bill"; // array of 5 chars
char *name2 = "Fred"; // pointer to 5 chars
int main(int argc, char **argv) {
It is also possible to subtract two pointers, which should be pointers to the same array.
int arr[40];
The following are equivalent:
for (int i = 0; i < 40; ++i)
arr[i] = arr[i] + 5;
int *end = arr + 40;
for (int *p = arr; p != end; ++p)
*p = *p + 5;
Note: arr + 40 cannot be dereferenced.
public interface java.util.Iterator {
boolean hasNext();
Object next();
void remove(); // not always supported
}
(Because Java does not support genericity,
the result of next() must be cast to the required type.)
list<string> names;
...
for (list<string>::iterator p = names.begin();
p != names.end(); ++p)
cout << *p << '\n';
Each sequence includes a type iterator for its iterators,
and two iterators:
typedef int time;
typedef char * cstr;
typedef deque<string> phrase;
typedef vector<vector<double> > matrix;
(We can also do this in C, but only outside functions.)
We can use a typedef to introduce an abbreviation for the iterator type:
typedef list<string>::iterator iter;
for (iter p = names.begin(); p != names.end(); ++p)
cout << *p << '\n';
| C | STL | ||
| array | arr | container | c |
| pointer | p | iterator | p |
| start pointer | arr | start iterator | c.begin() |
| end pointer | arr + LENGTH | end iterator | c.end() |
| increment | ++p | ++p | |
| dereference | *p | *p |
e.g. the iterator of slist (singly linked lists).
e.g. the iterator of list.
e.g. the iterator of vector or deque.
template <typename Iterator, typename Elem>
int count(Iterator start,
Iterator finish, const Elem & v) {
int n = 0;
for (Iterator p = start; p != finish; ++p)
if (*p == v)
n++;
return n;
}
There several requirements here
(checked at instantiation):
Here is an example of its use:
list<string> names;
string s;
....
int n = count(names.begin(), names.end(), s);
cout << s << " occurs " << n << " times\n";
In the above use,
map<string, int> table;
...
typedef map<string, int>::iterator Iter;
for (Iter p = table.begin(); p != table.end(); ++p)
cout << p->first << " -> " << p->second << '\n';