Other C++ Features • True reference parameters • Default arguments

advertisement
Other C++ Features
• True reference parameters
Readings: 3.3,3.5-3.7
• Default arguments
Readings: 4.1-4.7
• C++ Dynamic Memory
Readings 5.1-5.8
Outline
• True reference parameters
how to define, how to call, how to use
• Default arguments
how to define, how to call, order effects, legal values
• C++ Dynamic Memory
new, delete keywords
allocating/deleting single instance
allocating/deleting 1D array
allocating/deleting 2D array
True Reference Parameters
C++ has another way of passing parameters -- true
reference parameters
A true reference parameter gives you a way to change a
variable that is not part of a function without passing it
as a pointer
In a function definition you indicate a function parameter
by putting an & after the type (no *)
Type& Pname
In a call to the function you give the name of the variable
The parameter becomes another way to refer to the
variable
A Simple True Reference Parameter
void updateInt(int& num) {
// num becomes a synonym for the var
// used in the function call
num = num + 1;
}
int X = 5;
updateInt(X); // num becomes name for X
cout << X << endl; // Prints 6\n
Reference to a Pointer
• Reference parameters useful for changing pointer vars (so
you don’t have to pass a pointer to a pointer)
• Put & after * with type
• Example:
void InitList(LLStruct*& start) {
start = 0;
}
LLStruct *ListStart;
InitList(ListStart);
Reference to a Structure
• Can also pass a reference to a structure:
struct TIME { // more on this later
int hours, minutes, seconds;
};
void springForward(TIME& thetime) {
thetime.hours += 1;
}
TIME currtime = {0, 0, 0};
springForward(currtime);
Default Parameter Values
• In C++ you can supply default values for
parameters
– when calling such functions you can leave out
arguments for some of these parameters
– the default values of those parameters are used in place
of arguments
– the function therefore can be called with a different
number of arguments
Specifying Default Values
• Format of parameter: Type Pname = DefaultVal
– DefaultVal can be any appropriate expression (not
necessarily a constant)
• Rules for including
– may have more than one default parameter
– default parameters must be the last parameters for
function
– the order of the default parameters matters
• can leave out last default parameter, last two, last three, etc.,
but can not pick and choose (can’t leave out last and third to
last)
Default Example
void deffunc(int a, float b = 2.0, int c = 3,
char d = ‘A’) {
cout << a << ‘ ‘ << b << ‘ ‘ << c << ‘ ‘ << d
<< endl;
}
calls:
deffunc(1);
deffunc(1,4.0);
deffunc(1,5.0,6);
deffunc(1,7.0,8,’B’);
//
//
//
//
Outputs
Outputs
Outputs
Outputs
1
1
1
1
2.0
4.0
5.0
7.0
3
3
6
8
A\n
A\n
A\n
B\n
Can Use Objects as Defaults
• Objects must be available (generally global)
• Example:
void Read_To_Newline(istream& ins = cin) {
while (ins.get() != ‘\n’);
}
– when called, cin is used as parameter ins unless an
argument is supplied
Read_To_Newline();
// Reads from keyboard (cin)
Read_To_Newline(myin); // Reads from file myin connected to
Using Expressions as Defaults
• Can use a complex expression as a default value
– as long as the expression is well-defined (i.e., generally
involves global variables/functions)
int default_array_length = 20;
char *allocate_array(unsigned int size =
((default_array_length * sizeof(char)) + 1)) {
…
}
Dynamic Memory Allocation
• Space on the heap is allocated using the keyword
new to create a new instance (similar to malloc)
• The space can be returned to the heap using the
keyword delete (similar to free)
• There are no routines corresponding to calloc and
realloc (though it is easy enough to write your
own version of calloc)
Allocating a Single Element
• Use new Type to create element of type Type
• Examples:
int* iptr = new int;
float* fptr = new float;
char* cptr = new char;
int** iptrptr = new int*;
– each of these variables points to a new element of the
appropriate type (a lot easier than malloc, eh?)
– can also use new during code:
int* iptr2;
iptr2 = new int; // As opposed to
// iptr2 = (int *) malloc(sizeof(int));
Initializing the Resulting Space
• Using the basic format (new Type), the resulting space is
not initialized
• If you add an empty pair of parentheses (), the space is
initialized to 0
• If you add a pair of parentheses with an appropriate value
in between (val), the space is initialized to val
• Examples
int i1ptr = new int;
// new space, ? val
int i2ptr = new int();
// new space, 0 val
int i3ptr = new int(42); // new space, 42 val
Deleting an Instance
• Use delete keyword followed by pointer to space
allocated on heap:
delete pointer;
• Examples:
int* iptr = new int;
float *fptr = new float;
int** iptrptr = new int*;
…
delete iptr; // free space iptr connected to
delete fptr;
delete iptrptr;
Allocating a 1-Dimensional Array
• Use square brackets, size after type in new:
new Type[rows]
• Variable should be a pointer to type Type
• Example:
int size = 10;
int* iarray = new int[size];
float* farray = new float[size*2];
int** iptrarray = new int*[size+1];
– error to put parentheses around type
Releasing 1D Array
• To release 1-dimensional array use delete, but put
[] between keyword delete and pointer:
delete [] aptr;
• The brackets inform C++ you are giving back a
group of memory
• Example:
int* iarray = new int[10];
…
delete [] iarray;
Allocating Space for String
• Use new to allocate space for length of string plus
one extra for delimiter
• Example:
char *basestr = “hello”;
char *copystr;
copystr = new char[strlen(basestr)+1];
strcpy(copystr,basestr);
Allocating 2-Dimensional Array
• Use technique similar to what we did in C:
Type** twodname;
twodname = new Type*[dimension1];
for (int d1 = 0; d1 < dimension1; d1++)
twodname[d1] = new Type[dimension2];
• Releasing array:
for (int d1 = 0; d1 < dimension1; d1++)
delete [] twodname[d1];
delete [] twodname;
int **A;
2D Array Example
A = new int*[5];
for (int i = 0; i < 5; i++) {
A[i] = new int[8];
for (int j = 0; j < 8; j++)
A[i][j] = i + j;
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 8; j++)
cout << setw(3) << A[i][j];
cout << endl;
}
for (int i = 0; i < 5; i++)
delete [] A[i];
delete [] A;
Example: Array of Strings
#include
#include
#include
#include
#include
<stdlib.h>
<iostream.h>
<iomanip.h>
<fstream.h>
<string.h>
void main() {
const int BUFSIZE = 256;
int maxlines = 32;
int numlines = 0;
ifstream fin;
ofstream fout;
char buffer[BUFSIZE];
char **lines = new char*[maxlines];
char **savelines;
Example: Array of Strings
cout << "File to read: ";
cin >> buffer;
fin.open(buffer);
if (!fin) {
cout << "Unable to open " << buffer << endl;
exit(0);
}
while (!((fin.getline(buffer,BUFSIZE)).eof())){
if (numlines == maxlines) {
maxlines *= 2;
savelines = lines;
lines = new char*[maxlines];
for (int i = 0; i < numlines; i++)
lines[i] = savelines[i];
delete [] savelines;
}
lines[numlines] = new char[strlen(buffer)+1];
strcpy(lines[numlines],buffer);
numlines++;
}
fin.close();
Example: Array of Strings
cout << "File to save: ";
cin >> buffer;
fout.open(buffer);
if (!fout) {
cout << "Unable to open " << buffer << endl;
exit(0);
}
for (int i = 0; i < numlines; i++)
fout << lines[i] << endl;
fout.close();
}
Download