PPT - The School of Electrical Engineering and Computer Science

advertisement
Cpt S 223 – Advanced Data Structures
C++ Review 2
Nirmalya Roy
School of Electrical Engineering and Computer Science
Washington State University
Topics



Parameter Passing
Return Passing
Destructor, copy constructor, operator=





Templates



Destructor
Copy constructor
operator=
Problems with default destructor, copy constructor,
operator=
Function templates
Class templates
Summary
Parameter Passing

C++ parameter passing techniques

Call by value


Call by constant reference


Appropriate for small objects that should not be altered by
function
Appropriate for large objects that should not be altered by
function
Call by reference

Appropriate for all objects that may be altered by function
Call by constant
reference
Call by value
Call by
reference
double avg(const vector<int>& arr, int n, bool & errorFlag);
Average of the first n integers in arr, and set errorflag to true if n is larger than
arr.size() or smaller than 1
Parameter Passing Rules


If the formal parameter should be able to change
the value of actual argument, then use call by
reference
Else if the value of the actual argument cannot be
changed by the formal parameters:


If the type is a primitive type, use call by value
If the type is a class type, then would generally be
passed using call by constant reference

However if the class types that are small (with only a single
built-in type) can be passed using call by value instead of call by
constant reference
Return Passing




Objects can also be returned using return by value,
return by constant reference, and occasionally
return by reference
For the most part, do not use return by reference
It is safe to return by value
If an object of a class type is being returned, it may
be better to use return by constant reference


avoid the overhead of a copy
Make sure the object returned will persist after
returning from the function call
Destructor, Copy Constructor, Operator=

In C++, classes come with 3 special functions
automatically written for you




Destructor
Copy constructor
operator=
These default functions may or may not be
appropriate for your class
Destructor



The destructor is called when an object goes out of
scope or is subject to a delete
By default, it calls the destructor on all data
members
Destructor should free up any resources that were
allocated during the use of the object (i.e. delete
objects creating using new), closing any opened
files, etc
Copy Constructor

A special constructor used to construct a new
object, initialized to a copy of the same type of
object
Copy Constructor (cont’d)
class IntCell {
public:
IntCell() {
storedValue = 0;
}
IntCell(int initialValue) {
storedValue = initialValue;
}
int read() {
return storedValue;
}
void write(int x) {
storedValue = x;
}
private:
int storedValue;
};
Copy constructor is called in the
following cases:
1. Declaration with initialization
IntCell B = C;
IntCell B(C);
2. An object passed using call by value
(instead of call by & or call by const &)
3. An object returned by value
(instead of by & or const &)
By default, copy constructor calls copy
constructors to each data members
Simple assignment for all data members
with primitive types (e.g. int, char, double etc)
operator=



operator= is called the copy assignment operator
operator= is called when objects on both sides of =
are already constructed
For example


IntCell B(0);
IntCell C(1);
B = C;
By default, operator= is called on each data member of objects
Problems with Default Destructor, Copy
Constructor, operator=
class IntCell {
public:
explicit IntCell(int initialValue = 0) {
storedValue = new int(initialValue);
}
int main() {
IntCell a(2);
IntCell b = a;
IntCell c;
int read() const {
return *storedValue;
}
c = b;
a.write(4);
cout << a.read() << endl << b.read();
cout << endl << c.read() << endl;
void write(int x) {
*storedValue = x;
}
return 0;
}
private:
int *storedValue;
};
What is the output?
What is the problem?
Problems with Default Destructor, Copy
Constructor, operator= (cont’d)




The class uses default destructor, copy constructor,
and operator=
The default destructor does not delete allocated
memory (memory leak), default copy constructor
and operator= only perform shallow copy (copy not
the object being pointed at, but simply the value of
the pointer variable)
What we want is deep copy (a clone of the entire
object is made)
For a class containing pointers, we need deep copy
so we must explicitly implement the destructor,
copy constructor, and operator=
Problems with Default Destructor, Copy
Constructor, operator= (cont’d)
class IntCell {
public:
explicit IntCell(int initialValue = 0);
IntCell(const IntCell & rhs);
~IntCell();
//copy constructor
//destructor
const IntCell & operator=(const IntCell & rhs); //copy assignment operator
int read() const;
void write(int x);
private:
int *storedValue;
};
Problems with Default Destructor, Copy
Constructor, operator= (cont’d)
// Initializer List
IntCell::IntCell(int initialValue) {
storedValue = new int(initialValue);
}
// Copy Constructor
IntCell::IntCell(const IntCell & rhs) {
storedValue = new int(*rhs.storedValue);
}
//Destructor
IntCell::~IntCell() {
delete storedValue;
Problems with Default Destructor, Copy
Constructor, operator= (cont’d)
//Copy Assignment Operator
const IntCell & IntCell::operator=(const IntCell & rhs) {
if (this != &rhs)
*storedValue = *rhs.storedValue;
return *this;
}
// Member Function
int IntCell::read() const {
return *storedValue;
}
//Member Function
void IntCell::write(int x) {
*storedValue = x;
}
Templates




Templates are for designing type-independent data
structures and algorithms
Type-independent means that the logic of the data
structures and algorithms does not depend on the
type of objects (i.e. the same logic works for any
data types)
Templates prevent recoding a piece of code for
each different type
2 types


Function templates
Class templates
Function Templates
Untemplatized Version
void output(const vector<int> & v) {
for (int i = 0; i < v.size(); i++)
cout << v[i] << endl;
}
void output(const vector<float> & v) {
for (int i = 0; i < v.size(); i++)
cout << v[i] << endl;
}
void output(const vector<char> & v) {
for (int i = 0; i < v.size(); i++)
cout << v[i] << endl;
}
Templatized Version
template <typename T>
void output(const vector<T> & v) {
for (int i = 0; i < v.size(); i++)
cout << v[i] << endl;
}
int main() {
vector<int> v1(37);
vector<float> v2(40);
vector<IntCell> v3(10);
//additional codes to fill in the
vector are not shown
output(v1);
output(v2);
output(v3); // illegal; operator <
undefined
return 0;
}
Class Templates
Zero may not be
a valid Object
template <typename Object>
class MemoryCell {
public:
explicit MemoryCell(const Object & initialValue = Object()) :
storedValue(initialValue) {
}
const Object & read() const {
return storedValue;
}
int main() {
void write(const Object & x) {
storedValue = x;
}
MemoryCell<int> m1;
MemoryCell<string> m2(“hello”);
private:
Object storedValue;
m1.write(37);
m2.write(m2.read() + “ world”);
cout<<m1.read()<<endl<<m2.read()<< endl;
};
return 0;
}
Class Templates (cont’d)





MemoryCell is like IntCell class but works for any
type called Object
Object should have a zero-parameter constructor, a
copy constructor, and copy-assignment operator
Note that the default parameter for constructor is
not 0, since 0 might not be a valid Object
Default parameter is the result of constructing an
Object with its zero-parameter constructor
Note:


MemoryCell is NOT a class; it is a class template
MemoryCell<int> and MemoryCell<string> are the actual
classes
Class Templates (cont’d)

In many cases, in implementing a class template,
the entire class with its implementation must be
placed in a .h file
Summary
We have reviewed
 Parameter Passing
 Return Passing
 Destructor, copy constructor, operator=
 Templates

tools for easing the design of type-independent data
structures and algorithms
Questions
?
Download