int i {10}; //curly braces, semicolon.
int j = 20; //how they used to define a variable before 2011
{curly
braces}
stays alive as long as the computer remains withing the
curly braces.
void f() //the definition of a function
{
int i {10};
cout << "Hello\n";
} //i dies here.
j.
j
hold a different value,
and each
j
dies before the next
j
is born.
i
dies when we escape from the loop.
int a[] {
0,
10,
20,
30,
40
};
const size_t n {size(a)}; //the number of array elements
for (int i {0}; i < n; ++i) {
int j {a[i] + 1};
cout << j << "\n";
}
main
function)
stays alive until the end of the program.
void f()
{
int i {10};
int j {20};
int k {30};
cout << "Hello\n";
} //Die here in the order k, j, i
In the above example,
the birth and death of
j
happen in between the birth and death of
i.
j
are
nested
inside of the birth and death of
i.
k
are nested inside of the birth and death of
j.
An analogy from presidential biography:
JFK
(1917–1963) was born after, and died before,
LBJ
(1908–1973).
JFK’s lifespan was therefore nested inside of LBJ’s lifespan.
Ditto for
Mozart
(1756–1791) and
Haydn
(1732–1809).
Each hexadecimal digit is an abbreviation for a series of four binary digits (four bits).
| decimal | binary | hexadecimal |
|---|---|---|
| 0 | 0 |
0 |
| 1 | 1 |
1 |
| 2 | 10 |
2 |
| 3 | 11 |
3 |
| 4 | 100 |
4 |
| 5 | 101 |
5 |
| 6 | 110 |
6 |
| 7 | 111 |
7 |
| 8 | 1000 |
8 |
| 9 | 1001 |
9 |
| 10 | 1010 |
A |
| 11 | 1011 |
B |
| 12 | 1100 |
C |
| 13 | 1101 |
D |
| 14 | 1110 |
E |
| 15 | 1111 |
F |
| 16 | 10000 |
10 |
| 17 | 10001 |
11 |
int i {10};
int *p {&i}; //Store the address of i into p.
//p is a "pointer" that "points to" i.
cout << *p << \n"; //Use an asterisk to "dereference" p:
//output the value of i.
int a[] { //an array of 5 ints
0, //p will point at this zero.
10,
20,
30,
40
};
int *p {a}; //Store the address of a[0] into p.
//a means &a[0]
//p "points to" a[0]
++p; //Now p points to a[1]
++p; //Now p points to a[2]
--p; //Now p points back to a[1]
This technology gives us a faster way to loop through an array:
int a[] { //an array of 5 ints
0,
10,
20,
30,
40
};
const size_t n {size(a)}; //the number of elements in the array
//The [square brackets] do a hidden multiplication and addition:
for (int i {0}; i < n; ++i) {
cout i << " " << a[i] << "\n";
}
for (int *p {a}; p < a + n; ++p) { //a means &a[0]; a+n means &a[n]
cout << *p << "\n";
}
[square
brackets]
instead of with
*
only if it points to an element in an array.
int a[] { //an array of 5 ints
0,
10,
20, //p will point at this 20
30,
40
};
int *p {a+2}; //point at the 20; a+2 means &a[2]
//Output the 20 and its left and right neighbors.
//Looks like an array whose subscripts go from -2 to +2 inclusive.
cout << p[-2] << "\n"; //output the 0
cout << p[-1] << "\n"; //output the 10
cout << p[0] << "\n"; //output the 20; p[0] means *p
cout << p[1] << "\n"; //output the 30
cout << p[2] << "\n"; //output the 40
#include <string>
using namespace std;
const string a[] {
"Staten Island",
"Brooklyn",
"Queens",
"Manhattan",
"Bronx"
};
const size_t n {size(a)}; //the number of burroughs
for (const string *p {a}; p < a + n - 1; ++p) { //a means &a[0]; a+n-1 means &a[n-1]
cout << p[0] << " and " << p[1] << " are connected by a bridge.\n";
}
Staten Island and Brooklyn are connected by a bridge. Brooklyn and Queens are connected by a bridge. Queens and Manhattan are connected by a bridge. Manhattan and Bronx are connected by a bridge.
int a[] { //an array of 5 ints
0,
10, //p will point at this 10
20,
30,
40 //q will point at this 40
};
int *p {a+1}; //point to the 10 (a+1 means &a[1])
int *q {a+4}; //point to the 40 (a+4 means &a[4])
cout << "p and q are pointing at elements that are " << q - p
<< " elements apart.\n";
p and q are pointing at elements that are 3 elements apart.
->
only if it points to a struct (or to an object).
struct point {
double x;
double y;
};
point origin {0.0, 0.0};
point *p {&origin}; //p points to the origin
cout << p->x << "\n"; //output origin.x
cout << p->y << "\n"; //output origin.y
//How we would have to output origin.x using p if they hadn't invented ->
cout << (*p).x << "\n"; //output origin.x
11011110 10101101 10111110 11101111
(blanks inserted for legibility)
DEADBEEF
const
at the start of a declaration,
or immediately after any asterisk.
const.
int i {10};
int *p1 {&i}; //p1 points to i. A plain old (non-constant) pointer
int *const p2 {&i}; //p2 points to i
//++p2; //The const prevents this.
//The const keeps p2 pointing to the same variable.
const int *p3 {&i}; //p3 points to i
//++*p3; //The const prevents this.
//The const prevents us from using p3 to change the value of i.
const int *const p4 {&i}; //p4 points to i
//++p4; //The righthand const prevents this.
//++*p4 //The lefthand const prevents this.
void f(int& a, int *p) //function definition
int main()
{
int i {10};
int j {20};
f(i, &j); //Suppose this was the only statement you glanced at.
}
void f(int& a, int *p) //function definition
{
++a; //Change the value of i.
++*p; //Change the value of j.
}
array.C,
array.txt.
localtime)
can return a pointer to a structure
in order to
return more than one result:
#include <chrono> //for class system_clock
#include <ctime> //for the function localtime and structure tm
using namespace std;
const auto now {chrono::system_clock::now()};
const time_t t {chrono::system_clock::to_time_t(now)};
const tm *const p {localtime(&t)};
cout << p->tm_year + 1900 << "\n";
cout << p->tm_mon + 1 << "\n";
cout << p->tm_mday << "\n";
int i {10};
cout << i << "\n"; //simple way to output the value of i
int *p {&i}; //p points to i
cout << *p << "\n"; //complicated way to output the value of i
Well,
not every variable has a name.
The only variables that have names are the variables created by definitions.
But in three cases variables cannot be created by definitions.
new
operator can
throw an exception
to carry the bad news to another part of the program.
ints,
is there any reason not to use an object of class
vector<int>
instead of a dynamically allocated block of memory?
*
and
++
to an “iterator” such as
it
just as you apply them to a pointer.
#include <iostream> #include <iomanip> //for the i/o manipulator setw #include <vector> //for class vector using namespace std; vector<int> v { //You can make a vector just like you make an array. 0, 10, 20, 30, 40 }; v.push_back(50); v.push_back(60); vector<int>::size_type n {size(v)}; for (int i {0}; i < n; ++i) { cout << i << " " << setw(2) << v[i] << "\n"; } for (auto it {begin(v)}; it != end(v); ++it) { cout << setw(2) << *it << "\n"; }
struct mystruct {
double x;
double y;
};
void f(mystruct *p); //function declaration
int main()
{
mystruct origin {0.0, 0.0};
f(&origin); //Pass the address of origin to f.
}
void f(mystruct *p) //function definition
{
cout << p->x << "\n";
}
class myclass {
private:
double x;
double y;
public:
myclass(double init_x, double init_y); //constructor declaration
void f(); //member function declaration
};
int main()
{
myclass origin {0.0, 0.0};
origin.f(); //Invisibly pass the address of origin to f.
}
myclass:myclass(double init_x, double init_y) //constructor definition
: x {init_x}, y {init_y}
{
}
void myclass::f() //member function definition
{
cout << x << "\n";
}
const member functions vs.
const member functionsoperator<<,
operator>>.
date::length.
date vs. class
ofstream)..h)
file vs. implementation
(.C)
file for a class
If an
operator
function needs to mention the privatre members of a class,
it will have to be a member function or a friend of the class.
(This is true of
any
function.)
The usual rules are:
One exception to the above rule:
If an
operator
function is a member function,
it is always a member function of the object to its
right
(i.e., its right operand).
date d; d += 10; //means d.operator+=(10); The operator+ is a member function of the d. d -= 10; //means d.operator-=(10); The operator- is a member function of the d. cout << d; //If this operator<< was a member function, //it would be a member function of the cout. cin >> d; //If this operator>> was a member function, //it would be a member function of the cin.
Therefore if the above
operator<<
needs to mention the private members of class
date,
the
operator<<
will have to be a friend function of class
date.
Ditto for
operator>>