700 likes | 938 Views
SECTION 3. C++ Pointer and Functions. L-value and R-value. L-Value and R-Value Two types of values are associated with a variable. – l-value : the address value of the variable. – r-value : the real value of the variable. The left hand side of an assignment operator requires an l-value.
E N D
SECTION 3 C++ Pointer and Functions
L-value and R-value • L-Value and R-Value • Two types of values are associated with a variable. • – l-value : the address value of the variable. • – r-value : the real value of the variable. • The left hand side of an assignment operator • requires an l-value.
L-value and R-value • Example: • int x = 10, • y = 20; • x = y; // r-value of y is stored in the l-value of x; • y = x; // r-value of x is stored in the l-value of y; • x = 1; // r-value of literal constant 1 is stored in the • // l-value of x • 1 = y; // error. no l-value for literal constant 1. • ++ x; // x=x+1 • ++ 10; // ?
Pointer definition • Syntax: • base type * pointer name; • where base type defines the type of variable the • pointer points to. • Example: • int * ptr1; // a pointer to integer. • int * * ptr2; // a pointer to pointer to integer • int * ptr1, ptr2; // a pointer and an integer
Figure of Memory Allocation • dynamic objectsmemory managed by • programmer;by explicitly • call of new/delete • Function parameters, • Local objects memory managed by • compiler; used for each • function call • global objects global data:object locations • are fixed value but can be • changed • Function definitions code and read-only • objects
Memory Allocation • In C++, operator new and delete are used to allocate and free storage dynamically. • int main(){ • int *ptr1; • float *ptr2; • ptr1 = new int; • // In C: ptr1=malloc (sizeof(int)); • ptr2 = new float; • // In C: ptr2=malloc (sizeof(float)); • *ptr1 = 20; • *ptr2 =13.5; • delete ptr1; • // In C: free(ptr1); • delete ptr2; • }
Dynamic Arrays • Example : • int main(){ • float *a; • int n; • cout << ``enter size of list:''; • cin >> n; • a = new float[ n ]; • // C code: a = malloc(n * sizeof(float)); • for(int i=0; i<n; i++) • cin >> a[i]; • delete [] a; • }
Dynamic Arrays Use delete [] when the dynamic object is an array.
Dynamic Allocation ofMulti-dimensional Array Example: #include <iostream> using namespace std; int main(){ int m,n cout << ``enter the number of rows and columns: ''<<'\n'; cin >> m >> n; int **a; //a is a pointer to pointer to integer a = new int*[m]; //a points to an array of integer pointer //the size of this pointer array is m
Dynamic Allocation ofMulti-dimensional Array for(int i=0; i<m; i++) //each pointer in the array points to a[i] = new int[n]; //an array of integer //the size of these integer arrays is n cout <<''Enter values for this ''<<m<<''by''<<n<<''array:\n''; for(int i=0; i<m; i++) for(int j=0; j<n; j++) cin >> a[i][j]; for (int i=0; i<m; i++) //deallocate memory delete [] a[i]; delete [] a; }
Dynamic Allocation of Multi-dimensional Array • Note: • In C++, new, new[], delete, delete[] are built-in operators • rather than library functions. • new, new[], delete, delete[] should be used together, and not mixed with C storage management functions (malloc, free). • Programmer should explicitly deallocate the memory of • dynamic objects.
Dynamic Allocation of Multi-dimensional Array Related problems: – memory leak – dangling pointer
Dynamic Memory Allocation • Questions: • Does the statement • delete ptr; • delete the pointer ptr or the object being referred by ptr?
C++ Reference Type • In C++, reference type provides an alternative name for an object. The definition of a reference is preceded by the & operator. • Example: • int x = 10; • int &ref1 = x; // ref1 is a reference to int x. • int *& ref2 = ptr // ref2 is a reference to int pointer ptr. • A reference is a name alias - Not a pointer !
C++ Reference Type • The main use of reference is for specifying arguments and return values for functions in general and for overloaded operators in particular. • When a reference is defined, it must be initialized to an object. • Once initialized, a reference can not be reassigned to refer to another object.
C++ Reference Type • Example: //sam7.cpp • int a, b=5; • int &ref = a; // a and ref both refer to same memory location! • // ref is an alias for a • a = 3; • ref = 3; // both affect a • ref = b; //ref=5 • ref++; //ref=6 • //Compared to pointer: • int *ptr; // ptr is a new object • ptr = &a; • *ptr = 3; • ptr = &b; // ok
C++ Reference Type • Reference types are usually used as function • parameters. It can • – increase code clarity, • – reduce function parameter costs, • – optimize compilation.
C++ Reference Type • A reference is just an alias, it’s different from pointer. • Some differences between a reference and a pointer: • A reference cannot be NULL • Once established a reference cannot be changed • An alias does not need dereferencing • A reference is declared by using the ampersand • All operators operate on the actual value not reference
C++ Reference Type • The most common use of reference is pass by reference to a function (allowing the function to change the actual value) • Example: • #include <iostream> • void passExample ( int & i ) { i++; i = i + 1; } • int main () • { int j = 5; • passExample(j); • cout << j << endl; return 0; • }
Functions in C++ • A function declaration ( function prototype ) consists of the function name, its return type, and the number and types of the function parameters. • Example: • int f(int, int); // declaration of f: • // f has two integer parameters • // and returns a integer • void g(); // declaration of g: • // g has no argument and returns nothing
Functions in C++ • A function body or function block is the function implementation enclosed in braces. • A function definition is composed of the function declaration and the function body. • Actual parameters: arguments provided at the function call; they are placed inside the call operator. • Formal parameters: parameters received by the function definition. • A function is evaluated when the function name is followed by the call operator ( ).
Functions in C++ • Note: • C++ is a strongly typed language. A function cannot be called unless it is previously declared. • The following two prototypes of main are supported by all C++ compilers. • int main() • {} • int main(int argc, char *argv[]) • {}
Parameter Type Checking • The arguments of every function call are type-checked during compilation. If there is a type mismatch, implicit conversion is applied if possible. • //sam8.cpp • void f( int ){ /* ... */ } • int x = 0; • bool flag = true; • char c = 'a'; • f( 10 ); // exact match • f( x ); // exact match • f( flag ); // match with a promotion • f( c ); // match with a promotion • f( 12.34 ); // match with a standard conversion • f( "hello" ); // mismatch • f( 12, 3 ); // mismatch
Call by Value • The default argument passing method in C++ is call by value. • Example: • void f(int x); • int main(){ • int a = 10; • f(a); • f(10); • } • void f(int x){ • x += 100; • }
Call by Value • During the first function call to f() • a is the actual parameter; x is the formal parameter • Because a is passed by value, its content is copied to the function’s parameter x • x and a are physically two different memory cells
Call by Reference • Call by reference can be simulated by using pointer and address passing. • Example: • void swap(int *a, int *b); • int main(){ • int x = 1; • int y = 2; • swap(&x, &y); • }
Call by Reference • void swap( int *a, int *b){ • int tmp; • tmp = *a; • *a = *b; • *b = tmp; • }
Call by Reference • The reference operator is usually used to specify a call-by-reference parameter in C++. • Example 1: //sam9.cpp • void f(int a, int &b); • int main(){ • int i = 0; • int j = 0; • f(i, j); • cout << i <<'\n'; //i=0 • cout << j <<'\n'; //j=1 • } • void f(int a, int &b){ • a++; • b++; • }
Call by Reference • Example 2: • void swap(int &a, int &b); • int main(){ • int x = 1; • int y = 2; • swap(x, y); • } • void swap(int &a, int &b){ • int tmp; • tmp = a; // not tmp = *a ! • a = b; • b = tmp; • }
Return by Value • When a function returns an object by value, the value to be returned is copied to a temporary storage before the function call ends, so the calling function can access the value. • Example: • int f(int x){ • x = x*x - 100 • return x; • } • int main(){ • int y = f(10); • }
Return by Reference • When a function returns an object by reference • using reference operator (&), the object is returned • as l-value. • Example: //sam10.cpp • int& f( int *ptr, int x ){ • return ptr[x]; • } • int main(){ • int a[100]; • cout<<f( a, 10 )<<endl; • }
Return by Reference • A local object should not be returned by reference since the lifetime of local object ends when the function call finishes. • Example: • int& add(int x, int y){ • int result = x + y; • return result; // error • }
Array Parameters • When an array is used as a function argument, the address of the array is passed. • Example: //sam11.cpp • void display(int num[10], int size); • int main(){ • int a[10]; • for(int i=0; i<size; i++) • a[i] = i; • display(a, 10); • } • void display(int num[10], int size){ • for (int i=0; i<size; i++) • cout<< num[i] <<'\n'; • }
Array Parameters • Three equivalent declarations of display • void display(int num[10], int size); • void display(int num[], int size); • void display(int *num, int size); • The function call display(a, 10) is an exact match of any of the above declarations.
Array Parameters • To avoid modifying the local copy of array elements, we can use the const specifier. • void display(const int *num, int size){ • // ... • }
Array Parameters • Since an array is passed as a pointer, the size of the array is not known in the function called. • Example: • void display( int num[10] ); • int main(){ • int i, j[2]; • display( &i ); // ok: &i is type int* • display( j ); // j is type int* • // but, potential run-time error • }
Default Argument • In C++, default values can be specified for function parameters, so the function can be called without being provided all the arguments. • Example: • void f( int x, double m=12.34 ); • int main(){ • f( 1, 1234.56 ); // ok • f( 1 ); // ok, m=12.34 • f(); // error! no default value for x • }
Default Argument • Default arguments can be provided by trailing arguments only. • void f( int x=1, double m, char s='a'); // wrong • void f( int x=1, double m=12.34, char s); // wrong • void f( int x, double m, char s='a'); // ok
Default Argument • Default arguments should be supplied in a function declaration, not in a function definition. • Example: • // file f.h • void f(int, int); • // file f.cpp • void f( int a = 2, int b = 3){ • // ... • }
Default Argument • Correct version: • // file f.h • void f(int a = 2, int b = 3); • // also ok: void f(int = 2 , int = 3); • // file f.cpp • void f( int a, int b){ • //... • }
Default Argument • For a previously defined function, additional default arguments can be specified using succeeding declarations. Thus, a general function can be customized for a more specific use. • Example: • The UNIX system library function chmod() changes the protection level of a file. It is declared as: • int chmod( char *filePath, int protMode );
Default Argument • chmod() can be redeclared to supply the protection mode value a default value of read-only. • #include <cstdlib> • int chmod( char *filePath, int protMode = 0444 );
Scope and Lifetime • Two questions: • How long does the object exist lifetime • The life time of a C++ object is either static, automatic, or dynamic. This is referred to as the storage class of an object. • Where the object can be used scope • C++ supports local scope, namespace scope and class scope.