C ++ study Note 3
Function summary:
A function is a computing unit with a name. It is vital to structure a program (even a small program. The function definition consists of the return type, function name, parameter table (which may be null), and function body. The function body is the statement block executed when a function is called. When calling a function, the real parameters passed to the function must be compatible with the corresponding parameter type.
Passing real parameters to the function follows the variable initialization rules. Parameters of the non-reference type are initialized with copies of the corresponding real parameters. Any modification to (non-referenced) parameters only applies to local copies, and does not affect the real parameters themselves. Copying large and complex values has an expensive cost. To avoid the overhead of transferring copies, you can specify the parameter as the reference type. Any modification to the referenced parameter directly affects the real parameter itself. Reference parameters that do not need to be modified as const references should be defined.
In C ++, functions can be reloaded. If the number or type of parameters in a function is different, the same function name can be used to define different functions. The compiler determines which function to call based on the real parameters used for function calling. The process of selecting a suitable function in the overload function set is called function matching.
C ++ provides two special functions: inline and member functions. It is recommended that the compiler directly expand the function code at the call point by specifying the function as inline. Inline functions avoid calling functions. A member function is a function that is a class member.
1. The function cannot return another function or the built-in array type, but can return a pointer to the function or to the array element:
// OK: pointer tofirst element of the array int * foo_bar (){/*... * // when defining or declaring a function, it is invalid to explicitly specify the return type: // error: missingreturn type test (double v1, double v2) {/*... */
2. function parameter table
The function parameter table can be empty, but cannot be omitted. Functions without any form parameters can be expressed by empty form parameters or a form parameter table containing a single keyword void. For example, the following statement about process is equivalent:
void process() { /*... */ } // implicit void parameter list void process(void){/* ... */ } // equivalent declaration
The form parameter table consists of a series of parameter types separated by commas (,) and (optional) parameter names. If two parameters
If they have the same type, the type must be declared again:
int manip(int v1, v2){ /* ... */ } // error int manip(int v1, intv2) { /* ... */ } // ok
Parameters with the same name cannot appear in the parameter table. Similarly, variables with local functions cannot use the same name as any function parameter.
Parameter names are optional, but generally all parameters must be named in the function definition. Parameters must be named before they can be used.
3. parameter transfer
Every time a function is called, all the parameters of the function are re-created. The passed parameters will initialize the corresponding parameters.
The initialization of the parameter is the same as that of the variable: If the parameter has a non-reference type,
Copy the value of the real parameter. If the parameter is of the reference type, it is only the alias of the real parameter.
4. Limitations of copying real parameters
Copying a real parameter is not applicable in all cases. It is not suitable for copying a real parameter, including:
• When you need to modify the value of the real parameter in the function.
• When a large object needs to be passed as a real parameter. For actual applications, the time and storage space cost of copying objects often exceeded.
• When there is no way to replicate objects.
5. More flexible reference to const
If a function has a common non-const reference parameter, it cannot be called through the const object.
After all, the function can modify the passed object at this time, which violates the const feature of the real parameter.
However, it is easy to ignore that when calling such a function, passing an right value or an object of the type to be converted is also not allowed:
// function takes anon-const reference parameter int incr(int &val) { return ++val; } int main() { short v1 = 0; const int v2 = 42; int v3 = incr(v1); // error: v1 is not an int v3 = incr(v2); // error: v2 is const v3 = incr(0); // error: literals arenot lvalues v3 = incr(v1 + v2); // error: addition doesn't yield anlvalue int v4 = incr(v3); // ok: v3 is a non const objecttype int }
6. Pass the reference to the pointer-pointer exchange
Suppose we want to write a function similar to swap that exchanges two integers.
Needle exchange. * Defining pointer is required and reference is defined. Now the question is how
To get reference to the pointer. Here is an example:
// swap values of twopointers to int void ptrswap(int*&v1, int *&v2) { int *tmp = v2; v2 = v1; v1 = tmp; }
The definition of the parameter int * & v1 should be understood from the right to the left: v1 is a reference and associated with the pointer to the int type object.
That is to say, v1 is just the alias of any pointer passed into the ptrswap function.
Override the main function in Section 7.2.2 and call the ptrswap switch pointer to the values of 10 and 20 respectively:
Int main () {int I = 10; int j = 20; int * pi = & I; // pi points to I int * pj = & j; // pj points to j cout <"Before ptrswap (): \ t * pi:" <* pi <"\ t * pj: "<* pj <endl; ptrswap (pi, pj); // now pi points to j; pj points to I cout <" After ptrswap (): \ t * pi: "<* pi <" \ t * pj: "<* pj <endl; return 0 ;}// after compilation and execution, this program generates the following results: Before ptrswap (): * pi: 10 * pj: 20 After ptrswap (): * pi: 20 * pj: 10
7. Never return a reference to a local object
It is important to understand the returned reference: Never return a reference to a local variable. When the function execution is complete, the storage space allocated to the local object is released. In this case, the reference to a local object will point to an uncertain memory. Consider the following program:
// Disaster: Functionreturns a reference to a local object const string&manip(const string& s) { string ret = s; // transform ret insome way return ret; // Wrong:Returning reference to a local object! }
This function will cause an error during running because it returns a reference to a local object. When the function execution is complete,
The storage space occupied by the string ret is released, and the return value of the function points to the memory space that is no longer valid for this program.
8. Never return a pointer to a local object.
The return type of a function can be the majority. In particular, the function can also return pointer types. Like returning a local object reference, returning a pointer to a local object is also incorrect. Once the function ends, a local object is released, and the returned pointer is a pointer to a non-existing object.
9. inline functions
Calling a function is much slower than solving an equivalent expression. On most machines, calling a function requires a lot of work. Before calling a function, you need to save the register and restore it when it returns; copy the real parameter; the program must also be switched to a new position for execution.
Specify a function as an inline function (usually) to expand it in the "inline" area on each call point in the program.
Suppose we define shorterString as an inline function, then we call:
cout <<shorterString(s1, s2) << endl;
During compilation, it is expanded:
cout <<(s1.size() < s2.size() ? s1 : s2) << endl;
This eliminates the extra execution overhead of writing shorterString into a function.
This eliminates the extra execution overhead of writing shorterString into a function.
// inline version:find longer of two strings inline conststring & shorterString(conststring &s1, const string &s2) { return s1.size() <s2.size() ? s1 : s2; }
Inline indicates that it is only a suggestion for the compiler. the compiler can ignore this.
In general, the inline mechanism applies to small, few rows of functions that are often called.
Most compilers do not support inline recursive functions. A function with 1200 rows is unlikely to be expanded inline at the call point.
Inline functions should be defined in the header file, which is different from other functions.
10. overload and scope
The general scope rules also apply to the names of overloaded functions. If a function is declared locally
The function of the same name declared in the outer scope will be blocked rather than reloaded. It is inferred that each version of the overload function should be declared in the same scope.
Generally, it is unwise to declare a function locally. The function declaration should be placed in the header file.
/* Program for illustration purposes only: * It is bad style fora function to define a local variable * with the same nameas a global name it wants to use */ string init(); // the name init hasglobal scope void fcn() { int init = 0; // init is local andhides global init string s = init(); // error: global init is hidden }…void print(const string &); void print(double); // overloads the print function void fooBar(int ival) { void print(int); // new scope: hides previousinstances ofprint print("Value:"); // error:print(const string &) is hidden print(ival); //ok: print(int) is visible print(3.14); //ok: calls print(int); print(double) is hidden }
11. Candidate Functions
Call the overload function set considered. The function in this set is called a candidate function. The candidate function is a function with the same name as the called function,
Feasible Functions
Select one or more functions from the candidate functions. They can be called using the real parameters specified in the call. Therefore, the selected function is called a feasible function.
12. overload and const Parameters
Function overloading can be implemented based on whether the referenced parameter of a function points to a const object or a non-const object. Defining referenced parameters as const to overload a function is legal, because the compiler can determine which function to call based on whether the real parameter is const:
Recordlookup(Account&); Record lookup(constAccount&); // new function const Account a(0); Account b; lookup(a); // calls lookup(const Account&) lookup(b); // calls lookup(Account&)
If the parameter is a common reference, the const object cannot be passed to the parameter. If the const object is passed, only the version with the const reference parameter is the feasible function called.
13. pointer to function
A function pointer is a pointer to a function rather than an object.
14. function pointer
The function pointer type is quite lengthy. Using typedef to define synonyms for pointer types can greatly simplify the use of function pointers:
typedef bool(*cmpFcn)(const string &, const string &);
When the function name is referenced but the function is not called, the function name is automatically interpreted as a pointer to the function. Assume there are functions:
// compares lengthsof two strings boollengthCompare(const string &, const string &);
Except for the left operand used for function calls, any use of lengthCompare is interpreted as the following type of pointer:
Bool (*) (const string &, const string &); // you can use the function name to initialize or assign a value to the function pointer: cmpFcn pf1 = 0; // OK: unboundpointer to function cmpFcn pf2 = lengthCompare; // OK: pointer typematches function's type pf1 = lengthCompare; // OK: pointer type matchesfunction's type pf2 = pf1; // OK: pointer types match // in this case, directly referencing the function name is equivalent to applying the address obtaining operator on the Function Name: cmpFcn pf1 = lengthCompare; cmpFcn pf2 = & lengthCompare;
Function pointers can only be expressed by functions of the same type, function pointers, or 0-value constants.
Type to initialize or assign values.
Initializes the function pointer to 0, indicating that the pointer does not point to any function.
There is no conversion between pointers pointing to different function types:
string::size_typesumLength(const string&, const string&); boolcstringCompare(char*, char*); // pointer tofunction returning bool taking two const string& cmpFcn pf; pf = sumLength; // error: returntype differs pf = cstringCompare; // error: parameter typesdiffer pf = lengthCompare; // ok: function and pointertypes match exactly
15. Call a function through a pointer
A pointer to a function can be used to call the function it points. You do not need to use the unreferenced operation.
To directly call the function through the pointer:
cmpFcn pf =lengthCompare; lengthCompare("hi","bye"); // direct call pf("hi","bye"); //equivalent call: pf1 implicitly dereferenced (*pf)("hi","bye"); //equivalent call: pf1 explicitly dereferenced
If the pointer to the function is not initialized or has a value of 0, the pointer is not
Can be used in function calls. Only when the pointer has been initialized or assigned
A function can be safely used to call a function.
16. pointer to the overload Function
The C ++ language allows the use of function pointers to overloaded functions:
Extern voidff (vector <double>); extern voidff (unsigned int); // which functiondoes pf1 refer? Void (* pf1) (unsignedint) = & ff; // ff (unsigned) // the pointer type must exactly match a version of the overloaded function. If no exact match function exists, initialization or assignment of the pointer will lead to a compilation error: // error: no match: invalid parameter list void (* pf2) (int) = & ff; // error: no match: invalid return type double (* pf3) (vector <double>); pf3 = & ff;