390 likes | 536 Views
EE4E. C++ Programming. Lecture 1 From C to C++. Contents. Introduction Variables Pointers and references Functions Memory management. Introduction. C++ was developed at the Bell laboratories in the mid 1980's ANSI C is retained as a sub-set of C++ C++ was designed to support
E N D
EE4E. C++ Programming Lecture 1 From C to C++
Contents • Introduction • Variables • Pointers and references • Functions • Memory management
Introduction • C++ was developed at the Bell laboratories in the mid 1980's • ANSI C is retained as a sub-set of C++ • C++ was designed to support • Procedural programming • Modular programming • Data abstraction • Object-oriented programming
Object-oriented v Procedural • C supports procedural programming • The solution to a programming problem is through the use of a series of function (or procedure) calls • These functions may well use data structures but these are secondary to the solution of the problem
C++ supports object oriented programming • The solution to a problem is through the design of software units (objects) which have well controlled interaction • An object’s functions (methods) and data are on an equal footing • There is a lot more to it than this (for example inheritance and polymorphism) • This course is intended to give you a good grounding in understanding object oriented programming and design • First however, we must make the transition between C and C++
Variables • C++ is much less restrictive than C in where variables can be declared and initialized • In C++, variables can be declared and initialized anywhere, not just at the start of a main program or function block • However, this means the programmer has to have a good understanding of the rules of variable scope and lifetime (which are fairly obvious!)
A simple C++ program int main() { int k=1; // initialization if (k==1) { k++; int j; // declaration j=i+1; } return 0; }
The scope and lifetime rules of variables are fairly obvious • Typically the scope (and lifetime) of automatic variables is the innermost program clause • Scope equals lifetime except for static variables • Scope errors are picked up by the compiler
Example int main() { int x=1; // Scope is the whole program int y=2; // Scope is the whole program if (x==y) { int z=x*y; } else { int w=x+y; // OK z=2*w; // Scope error } return 0; }
Pointers and references • A pointer can be set up to access a variable exactly as in C : int x = 1; int* px=&x; (*px)++; // increments x (px)++; // increments the pointer
x px int x = 1; int* px=&x; 1 (*px)++; 2 px++;
A reference is an alternative name for a variable • The variable can be accessed through its reference • References can often be used in place of pointers int x = 1; int& rx=x; // reference to x rx++; // increments x
x, rx int x = 1; int& rx=x; 1 rx++ 2
Comparison between pointers and references • A pointer occupies physical memory • A pointers value can be changed (the pointer can be re-assigned) • A pointer can be null • A reference can not be re-assigned • A reference must be initalized int& rx; // un-initialized reference!
Uses of references • The main use is in function arguments and return values • They simplify the syntax of pass by reference which, in C, is through the use of pointers • Also they can express object dependencies • One object can contain a reference to another which is more efficient than full object aggregation (see later)
Functions • Function call and usage is the same as in C (but ANSI-style only!) • Extra features of function usage include : • Passing function arguments using references • Returning references • Function overloading • Default parameters • Inline functions
Passing function arguments by reference • In C++ (and C) function arguments are passed by value and by reference • Pass by reference in C is implemented through the use of pointers • A side effect is that the function may change the value of its actual argument on exit
void func(int arg1, int* arg2) { // arg1 passed by value, arg2 passed by reference arg1++; (*arg2)++; } void main() { int i,j ; i=j = 0; func(i,&j); // i=0, j=1 }
void func(int arg1, int& arg2) { // arg1 passed by value, arg2 passed by reference arg1++; arg2++; } void main() { int i,j ; i=j = 0; func(i,j); // i=0, j=1 } • We can get the same effect by passing a reference to the actual argument(s)
Simpler syntax as we don’t need to remember to de-reference formal arguments inside the function • However, functions with side-effects which change the values of the arguments is not good programming • Better to get the functions to return an updated argument • One situation which is common however is to pass large objects by reference • Removes the overhead of actual->formal argument copying if passed by value • A constant reference is used to prevent updating the object inside the function
void func(const large_structure& arg1) { // Constant reference prevents updating . . }
Functions returning references • A function can return a reference to an object • Allows function calls to be used as lvalues • They can appear on the left hand side of assignments • This is a nice programming trick as long as we know what we are doing
Example int a[20]; int zero=0; int& access(int index) { if ((index>=0)&&(index<20)) return a[index]; else return zero; } void main() { int val1=access(7); // val1=a[7] access(8)=20; // a[8]=20 }
The second assignment only works because access() returns a reference • Essentially it returns an alternative name for a[index] which means it can then be updated • Note that this function can not simply return 0 • It has to return something that we can take the address of (an lvalue) • Hence it returns zero – a variable containing 0
Overloaded function names • Function overloading enables several functions with the same name to be defined • These functions must have different sets of arguments (either type or number of arguments) • The C++ compiler selects the function with the best match of the arguments list to the one that has been called
Example – an overloaded power() function • We can supply several implementations of the power() function depending on the argument types • Integer exponent • Floating point exponent
double power(double a, int b) // Integer exponent { // Computes ab if (b == 0) return 1.0 else if (b > 0) { double r = 1.0; for (int i = 0; i < b; i++) r *= a; return r; } else { double r = 1.0; for (int i = 0; i < b; i++) r /= a; return r; } }
double power(double a, float b) // Floating point exponent { return(exp(b * log(a))); } int main(void) { double c = power(2.0,4) // c=24 (Integer exponent) double d = power(2.7182818,0.5) // d = e }
This is a powerful feature and allows the power() function to be implemented for a range of (user defined) data types • Complex numbers • Matrices • Function overloading is very often used to enable us to initialize objects in different ways (see later) • C++ also allows us to redefine the actions of operators (operator overloading) (see later)
Functions with default arguments • This is a simple feature of C++ whereby we can provide default values for trailing function arguments • Useful for functions with long argument lists
double power(double a, double b = 2.0) { return(exp(b * log(a))); } int main(void) { double c = power(4.0) // c = 42 double d = power(4.0,10.0) // d = 410 }
Inline functions • The use of inline functions is a technique for increasing the speed of small functions • The compiler performs inline code expansion to replace function calls with the actual code of the function • This is more efficient than performing a jump to the memory location of the function • Increases the size of the executable code • Only use if the function body is a few lines of code
Keyword inline indicates that the function is inline • Often used to define class methods within the class declaration (see later) inline int max(int a, int b) { return (a >= b) ? a : b; }
Memory management • C++ has an identical memory management system to C • There are 3 types of memory (variables) • Automatic • Dynamic • Static • Like C (but unlike Java) C++ does not have automatic garbage collection
Automatic variables • Memory allocated each time the variable definition is executed and automatically destroyed when the containing block terminates • Dynamic variables • Memory is allocated and de-allocated by the programmer on the free store or heap • Static variables • Memory allocated once and not freed until the program terminates
Dynamic variables • Dynamic variable allocation is handled in C with the malloc() and calloc() functions • C++ also provides a new operator with which dynamic variables can be created • Like malloc() and calloc(), new returns a pointer to the variable allocated • C++ also provides a delete operator which frees up dynamic memory • new[] and delete[] can be used to allocate and de-allocate dynamic arrays
void main() { int* p; p = new int; // dynamically allocates an integer if (p!=0) { (*p)=2; } delete p; // dynamically allocate a 10 integer array int* q = new int[10]; q[0]=1; q[9]=2; delete[ ] q; }
An important point to note for advanced usage is that new is an operator and not a function (unlike calloc() and malloc()) • new can be overloaded (re-defined) so, for example, smart memory management routines can be created for user defined objects
And finally…… • We have looked at some enhancements C++ provides to C for procedural programming • Variable usage • References • Function overloading • Memory management • The next lectures will cover major additional features of C++ for object oriented programming • Classes • Inheritance • Polymorphism