• Nem Talált Eredményt

Parameter passing methods

In document Mechatronic Systems Programming in C++ (Pldal 115-118)

II. fejezet - Modular programming in C++

1. The basics of functions

1.3. Parametrizing functions

1.3.1. Parameter passing methods

int main(){

const int degree = 3;

double coefficients[degree + 1] = { 5, 2, 3, 1};

cout << Polynomial(2,degree,coefficients)<< endl; // 29 }

1.3.1. Parameter passing methods

In the language C++ parameters can be grouped in two categories on the basis of how they are passed. There are input parameters passed by value and variable parameters passed by reference.

1.3.1.1. Passing parameters by value

If parameters are passed by value , it is their value that is passed to the called function. The parameters of the function are initialised to the passed values, and after, the relation between these arguments and parameters ends. As a consequence, the operations carried out on parameters have no effect on the arguments with which the function is called.

Arguments can only be expressions, the type of which can be converted into the type of the corresponding parameters of the called function.

The function enumber() returns the approximate value of e by summing up the first n+1 elements of the sequence:

double enumber(int n) { double f = 1;

double eseq = 1;

for (int i=2; i<=n; i++) { eseq += 1.0 / f;

f *= i;

}

return eseq;

}

The function enumber() can be called by any numeric expression:

int main(){

long x =1000;

cout << enumber(x)<< endl;

cout << enumber(123) << endl;

cout << enumber(x + 12.34) << endl;

cout << enumber(&x) << endl;

}

When it is first called, the value of the variable x of type long is passed to the function converted to type int. In the second case, the value of the parameter becomes a constant of type int. The argument of the third call is an expression of type double, the value of which is converted to an integer before it is passed. This conversion may provoke data loss - that is why the compiler sends us an alert message. The last case is an odd-one-out in the list of the calls since in that case, the compiler rejects to convert the address of the variable x to an integer. Since type conversions of this type can lead to run-time errors, conversions have to be asked for separately:

cout << enumber((int)&x) << endl;

If the value of an external variable is intended to be modified within the function, it is the address of the variable that have to be passed and the address has to be received as a parameter of pointer type. As an example, let's have a look at the classical function swapping the values of two variables:

void pswap(double *p, double *q) { double c = *p;

*p = *q;

*q = c;

}

int main(){

double a = 12, b =23;

pswap(&a, &b);

cout << a << ", " << b<< endl; // 23, 12 }

Arguments may also be expressions, but in that case these expressions have to be left value expressions. It should be noted that arrays are passed to functions by their beginning address.

If the type qualifier const is placed in the parameter list, we can restrict the modification of the memory space to which a pointer points ( const double *p) and restrict the modification of the value of the pointer ( double * const p) within a function.

1.3.1.2. Passing parameters by reference

Parameters passed by value are used as local variables in functions. However, reference parameters are not independent variables; they are only alternative names for the arguments provided in a function call.

Reference parameters are marked with a & character placed between the type and the parameter name in the function header. When the function is called, the argument variables have to have the same type as that of parameters. The function swapping the value of variables becomes simpler if we use parameters passed by reference:

void rswap(double & a, double & b) { double c = a;

a = b;

b = c;

}

int main(){

double x = 12, y =23;

rswap(x, y);

cout << x << ", " << y << endl; // 23, 12 }

The value (right-value) and the address (left-value) of a reference parameter equals with the value and the address of the referenced variable, so it completely replaces the latter.

It should be noted that the compiled code of the functions pswap() and rswap() are completely the same in Visual Studio. That is why it is not more efficient to use pswap() in C++ program codes.

Independently of the parameter passing method, compilers allocate memory space for parameters in the stack. In the case of value parameters, the size of the allocated memory depends on the type of the parameter; therefore it can be really big, while in the case of reference parameters it is the pointer size used in the given system that counts. In the case of a bigger structure or object, we should not only consider the increased memory need but also the longer time a function call requires.

In the following example, a reference to a structure is passed to a function but we would like to prevent the modification of the structure within the function. For that purpose, the most efficient method is to use a parameter of constant reference type :

#include <iostream>

void MinMax(const svector & sv, int & mi, int & ma) { mi = ma = sv.a[0]; space is required in the stack, however accessing parameters within the function is more efficient by using value type parameters.

Constant reference parameters completely replace constant value parameters, so any expression (not only variables) can be used as arguments. This fact is demonstrated by the example determining the greatest common divisor of two numbers:

int main() {

cout << Gcd(24, 32) <<endl; // 8 }

In document Mechatronic Systems Programming in C++ (Pldal 115-118)