Function definition and declaration (function parameter passing/return value/overloading (call matching)/function pointer)
function named code block can have 0/multiple parameters usually produce a result can be overloaded
6.1 Function basics
Function definition: a return type, a function name, a list of 0 or more formal parameters, and a function body
Call operator: The call operator is in the form of a pair of parentheses, which acts on an expression, which is a function or a pointer to a function. Inside the parentheses is a list of actual parameters separated by commas. The parameters of the initialization function
write function
Call functions
Initialize the formal parameters corresponding to the function with actual parameters
transfer control to the called function
The execution of the calling function is interrupted, and the called function starts executing
return statement:
returns the value in the return statement
Transfer control from the called function back to the calling function
formal parameters and actual parameters
The actual parameter is the initial value of the formal parameter (the order of evaluation of the actual parameters is not specified)
The type of the actual parameter must match the type of the corresponding formal parameter (argument item)
function parameter list
Can be empty but not omitted
The parameters in the parameter list are separated by commas and each parameter is a declaration with a declarator
Any formal parameter cannot have the same name, and local variables in the outermost scope of the function cannot have the same name as the formal parameter
The formal parameter name is optional but an actual parameter must be provided for it
function return type
The return type cannot be an array type or a function type, but can be a pointer to an array or a function
6.1.1 Local objects
Name scope: the part of the program text in which the name is visible
Object life cycle: the period of time an object exists during program execution
Local variables: parameters and variables defined inside the function body (will hide all other declarations with the same name in the outer scope)
automatic object
Ordinary local variables such as formal parameters
local static object
static type: Make the life cycle of local variables run through the function call and the time after
If there is no explicit initial value, perform value initialization Built-in type local static variables are initialized to 0
6.1.2 Function declaration
Function declaration (also known as function prototype) does not require a function body (no formal parameter names)
Three elements of a function: return type/function name/parameter type
Function declaration in header file
Header file declaration, source file definition, source file includes header file, compiler verifies function definition matches declaration
6.1.3 Separate compilation
When writing a program, divide it according to the logical relationship, and compile each file independently
compile and link multiple source files
$: system prompt; CC: compiler name; #: comment statement under the command line
If one of the source files is modified, just recompile the changed file to generate .o/.obj file (this file contains object code)
The compiler is responsible for linking object files together to form an executable
6.2 Parameter passing
Every time the function is called, its formal parameters will be recreated and initialized with the incoming actual parameters (the initialization mechanism is the same as that of variable initialization)
Pass by reference/pass by reference: the formal parameter is a reference type, which will be bound to the corresponding actual parameter (the reference formal parameter is the alias of the corresponding actual parameter)
Value/pass by value: the formal parameter and the actual parameter are two independent objects, and the value of the actual parameter is copied to the formal parameter
6.2.1 Pass-by-value parameters
Initialization of non-reference type variables The initial value is copied to the variable, and changes to the variable will not affect the initial value
pointer parameter
The pointer behavior is the same as other non-reference types: when performing a pointer copy, the value of the pointer is copied, and the two pointers after copying are different pointers (but the addresses they point to are the same)
C programmers often use pointer type parameters to access function external objects, and C++ recommends using reference type parameters instead of pointers
6.2.2 Pass-by-reference parameters
The operation on the reference actually acts on the object referred to by the reference
Use references to avoid copying
When a certain type does not support copy operations, only reference parameters can be used to access objects of this type
If there is no need to change the content of the formal parameter object, it can be defined as a reference to a constant (when the function does not need to modify the value of the reference formal parameter, it is best to declare it as a constant reference)
Use reference parameters to return additional information
Returning multiple results can define a new data type that contains multiple members
Pass additional reference arguments to the function
6.2.3 const parameters and actual parameters
Like other initializations, the top-level const is ignored when the formal parameter is initialized with an actual parameter. When the formal parameter has a top-level const, it can be passed to a constant or non-constant object. (Because the top-level const is ignored, when the function is overloaded, the formal parameters with or without the top-level const are the same, and such overloading cannot be performed)
pointer or reference parameter const
Parameters are initialized in the same way as variables are initialized
tip:
A non-const reference cannot be initialized with a literal value (but a const reference can be initialized)
cannot bind a normal reference to a const object
cannot bind a plain reference to a literal
Use constant references whenever possible
Using references instead of const references greatly limits the types of arguments a function can accept
For example, you cannot pass const objects/literal values/objects that require type conversion to ordinary reference objects
6.2.4 Array parameters
Array Special Properties
Copying of arrays is not allowed
When using an array, it is usually converted to a pointer (a pointer to the first element of the array)
However, the formal parameters can be written in an array-like form, such as (const int[])/(const int[10])but in the end the only formal parameters are(const int*)
The size of the array has no effect on the function call (but make sure you don't go out of bounds when using the array). Since the array is passed to the array in the form of a pointer, the function does not know the size of the array array, and the caller must provide some additional information for this
Three common techniques for managing pointer parameters
Use flags to specify array length
Applicable to situations where there is an obvious end tag and the tag will not be confused with ordinary data, such as a null character at the end of a C-style string
Use the standard library specification
Pass pointers to the first and last elements of the array (begin end)
Explicitly pass a formal parameter representing the size of the array
Determine the number of array elements through formal parameters, such as the number can beend(j)-begin(j)
Array parameters and const
When the function does not need to perform write operations on the array elements, the array parameter should be a pointer to const
Only when the function really needs to change the value of the element, define the formal parameter as a pointer to a non-constant
array reference parameter
C++ allows variables to be defined as references to arrays, and formal parameters can also be references to arrays ( (int (&arr)[10])brackets at both ends of the array name are essential)
The size of the array is part of the array type, as long as the dimension does not exceed the function body, the array can be used safely
passing multidimensional array
Multidimensional arrays are actually arrays of arrays
When passing a multidimensional array to a function, what is actually passed is a pointer to the first element of the array
The size of the second dimension of the array (and all subsequent dimensions) is part of the array type and cannot be omitted
All arguments are of the same type, and a initializer_liststandard library type named
Write a special kind of function, variadic templates, if the argument types are different
Special parameter type: ellipsis, variable number of actual parameters can be passed
initializer_listkeepsake
The number of arguments is unknown, but all arguments have the same type
An array used to represent values of a certain type
It is a template type but the elements in the object are always constant values and cannot modify the value of the object elements
initializer_listContains begin and end members, you can use the range for loop | | initializer_listOperations provided | |-----|-----| | initializer_list<T> lst;| Default initialization; Tempty list of type elements | | initializer_list<T> lst{a,b,c...};| lstThe number of elements is the same as the initial value many; lstelements of the list are copies of the corresponding initial values; the elements of the list are const. | | lst2(lst)| Copying or assigning an initializer_listobject does not copy the elements in the list; after copying, the original list and the copy share elements | | | - lst2 = lst| | lst.size()| the number of elements in the list | | lst.begin()| returns lsta pointer to the first element in | | | lst.end()returns lsta pointer to the next position of the microelement |
ellipsis parameter
It is convenient for C++ programs to access some special C code settings, these codes use the C standard library functions called varags
Only applicable to common types of c and c++, most class type objects cannot be copied correctly when passing ellipsis formal parameters
An ellipsis parameter can only appear in the last position of the parameter list
Ellipsis formal parameters do not require type checking
6.3 Return type and return statement
The return statement terminates the currently executing function and returns control to the place where the function was called
two forms return;andreturn expression;
6.3.1 Functions without return value
It can only be used for functions whose return type is void. A function returning void does not require a return because the last sentence of this type of function will implicitly execute the return
If you exit early in the middle of the void function, you can use return
If the return statement of a function whose return type is void has an expression, it must be another function that returns void
6.3.2 Functions with return values
As long as the function return value is not void, return must return a value, the return value type must be the same or can be implicitly converted to the return type of the function
There should also be a return statement after the loop containing the return statement
how the value is returned
return a value in exactly the same way as initialize a variable or parameter
Do not return references or pointers to local objects
Function termination means that references to local variables will point to memory areas that are no longer valid
Functions and Call Operators Returning Class Types
The call operator has the same precedence as dot and arrow operators, and is also left associative
reference returns an lvalue
Calling a function that returns a reference gets an lvalue, other return types get an rvalue
A call to a function that returns a reference can be used like any other lvalue, and can assign a value to the result of a function whose return type is a non-const reference, which cannot be assigned to the result of a call if the return type is a constant reference
list initializer return value
A function can return a list of values surrounded by curly braces, which is used to initialize the temporary value that represents the return of the function
If the list is empty, the temporary performs value initialization, otherwise the value returned is determined by the return type
If the function returns a built-in type, the list surrounded by curly braces contains at most one value, and the space occupied by the value should not be larger than the space of the target type; if the returned type is a class type, the class itself defines how the initial value is used
The return value of the main function main
The main function is allowed to end directly without a return statement, and the control reaches the end without a return statement. The compiler will implicitly insert a return statement that returns 0
The cstdlib header file defines two preprocessing variables, indicating success and failure. Because it is a preprocessing variable, std:: cannot be added in front, nor can it appear in the using statement.
EXIT_FAILURE
EXIT_SUCCESS
recursion
A function calls itself, there must be a path that does not contain recursive calls
recursive loop
A function keeps calling itself until the program stack space is exhausted
main function cannot call itself
6.3.3 Returning an Array Pointer
Arrays cannot be copied, so functions cannot return arrays, but pointers or references to arrays can be returned
Pointers or references returning arrays can be simplified using type aliases
Declare a function that returns an array pointer
To define a function that returns an array pointer, the array dimension must follow the function name
The formal parameter list of the function also follows the function name and the formal parameter list should precede the dimension of the array
Type(*function(parameter_list))[dimension]
use trailing return type
follows the formal parameter list and ->begins with a symbol
likeauto func(int i)->int(*)[10]
use decltype
Knowing which array the pointer returned by the function will point to, you can use the decltype keyword to declare the return type
decltype is not responsible for converting the array type into the corresponding pointer, so the result of decltype is an array. To indicate the return pointer, you need to add a * when the function declaration
6.4 Function overloading
Several functions in the same scope have the same name but different parameter lists
The compiler will infer the desired function based on the actual parameter type passed
The main function cannot be overloaded
Define overloaded functions
The overloaded function differs in the number of formal parameters or the types of formal parameters
Two functions are not allowed to be identical in all respects except the return type
Determine whether the types of two formal parameters are different
The formal parameter name is only used as a mnemonic, and whether it does not affect the content of the formal parameter list
Using type aliases is essentially no different for formal parameter lists
Overloading and const parameters
Top-level const does not affect the object passed into the function (a parameter with top-level const is indistinguishable from another parameter without top-level const)
If the formal parameter is a certain type of pointer or reference, function overloading can be realized by distinguishing whether it points to a constant object or a non-constant object. At this time, const is the bottom layer. The compiler can infer which function should be called by whether the actual parameter is a constant
const cannot be converted to other types, but non-const can be converted to const. When passing a non-constant object or a pointer to a non-constant object, the compiler will give preference to the non-constant version of the function
Whether to overload the function depends on which one is easier to understand
const_cast and overloading
When the actual parameter is not a constant, the actual parameter is first cast into a reference to const, and then the const version of the function is called. The const version returns a reference to the const type, which is actually bound to an initial non-constant actual parameter. so it can be cast back to a normal type& which is safe
call overloaded function
Function matching/overload determination: associate a function call with one of a set of overloaded functions (different number of parameters/independent parameter types)
There are three possibilities for overloading functions:
best match
No match: No function found that matches the arguments of the call
Ambiguous calls: more than one function can match, each of which is not the obvious best choice
6.4.1 Overloading and scope
If a name is declared in an inner scope, it will hide entities of the same name declared in outer scopes. Cannot overload function name in different scope
Once the required name is found in the scope, the compiler ignores the entity of the same name in the outer scope, and then checks whether the function call is valid
c++ name lookup happens before type checking
6.5 Special Purpose Language Features
Function-related language features: default arguments/inline functions/constexpr functions
6.5.1 Default arguments
Default argument: It is given the same value in many calls of the function. When calling a function with a default argument, the argument can be included or omitted.
One or more formal parameters can be defined to define default values. Once a formal parameter is assigned a default value, all subsequent formal parameters must have default values.
Call a function with default arguments
Just omit the actual parameter when calling the function
The actual parameters of the function call are parsed by position, and the default actual parameters are responsible for filling in the missing trailing parameters of the function call.
Reasonably set the order of the formal parameters, so that the formal parameters that do not use the default value often appear in the front, and the formal parameters that often use the default value appear in the back
default argument declaration
A formal parameter can only be assigned a default argument once in a given scope, and subsequent declarations of the function can only add default arguments to formal parameters that have no default values before, and all formal parameters to the right of the formal parameter must have default values
Normally default arguments should be specified in the function declaration, and the declaration should be placed in the appropriate header file
Default argument initial value
Local variables cannot be used as default arguments. Otherwise, an expression can be used as a default parameter as long as the expression type can be converted to the type required by the formal parameter.
Names used as default arguments are resolved in the scope of the function declaration, and evaluation occurs when the function is called
6.5.2 Inline functions and constexpr functions
Benefits of defining as a function:
easy to read and understand
ensure uniformity of behavior
Modifying functions is easier than equivalent expressions
can be reused
shortcoming:
Functions are slower than evaluating equivalence expressions
Function calls include:
Registers are saved before the call and restored on return
May need to copy arguments
The program goes to a new location to continue execution
Inline functions avoid the overhead of function calls
inline Let the function expand inline at the call site to eliminate the overhead of the function runtime
An inline function is just a request to the compiler, which the compiler can choose to ignore
The inlining mechanism is used to optimize small-scale, direct-flow, and frequently-called functions
Many compilers do not support inline recursive functions
constexpr function
For functions used in constant expressions, the return type and the types of all formal parameters must be literal value types, and there is only one return statement in the function body
constexpr functions are implicitly specified as inline functions
A constexpr function does not necessarily return a constant expression
Put inline functions and constexpr functions in header files
Inline functions and constexpr functions can be defined multiple times in the program, but multiple definitions must be completely consistent, usually defined in the header file
6.5.3 Debugging help
Header file protection, etc. The program can contain some code for debugging, but it is only used during development and shielded during release. Two preprocessing functions: assert and NDEBUG
assert preprocessing macro
Preprocessing names are managed by the preprocessor rather than the compiler, and preprocessing names can be used directly without providing a using statement. Like preprocessor variables, macro names must be unique within a program.
assert(expr)assert outputs a message and terminates program execution if the expression is false, or does nothing if the expression is true
The assert macro is often used to check conditions that cannot occur
NDEBUG preprocessing variable
If NDEBUG is defined, assert does nothing; if NDEBUG is not defined, assert will perform a runtime check
#define NDEBUGTurn off debug status using
Define your own debugging code, if NDEBUG is not defined, execute #ifndef和#endifthe code between; if NDEBUG is defined, these codes will be ignored
c++ compiler definition
_ _func_ _function name
Useful names for preprocessor definition program debugging
_ _FILE_ _filename string literal
_ _LINE_ _current line number integer literal
_ _TIME_ _compile-time string literals
_ _DATE_ _compile date string literal
6.6 Function matching
How to determine the overloaded function when the number of function parameters is equal and the type of some parameters can be converted from other types
Identify Candidate Functions and Feasible Functions
Candidate function: same name as called function; declaration visible at call site
Feasible function: the number of formal parameters is equal to the number of actual parameters provided this time; the type of each actual parameter is the same as the type of the formal parameter or can be converted to the type of the formal parameter
If no viable function is found, the compiler will report no matching function error
find the best match
Check the actual parameters provided by the function one by one, and find the feasible function whose formal parameter type best matches the actual parameter type
The closer the actual parameter types are, the better the match is; an exact match is better than a match requiring type conversion
function matching with multiple parameters
The compiler selects a function whose number of formal parameters meets the requirements and whose actual parameter type and formal parameter type can match, and checks each actual parameter in turn to determine which function is the best match. If there is one and only one function that meets the following requirements, the match is successful
The match of each argument of the function is no worse than the match required by other feasible functions
There is at least one argument whose match is superior to that provided by other feasible functions
When calling overloading, you should try to avoid mandatory type conversion, and the rationality of formal parameter design
6.6.1 Actual parameter type conversion
Argument-to-parameter type conversion level
exact match
The actual parameter type is the same as the formal parameter type
An argument is converted from an array or function type to the corresponding pointer type
Adds top-level const to an argument or removes top-level const from an argument
Matches achieved by const conversions
Matching of type promotion implementations
Arithmetic type conversion/pointer conversion
class type conversion
Matches requiring type promotions and arithmetic type conversions
Small integers are promoted to type int or larger integer types
Call is ambiguous when there are two possible arithmetic type conversions
Function matching and const arguments
When calling, the compiler decides which function to choose by whether the actual parameter is a constant
cannot bind a normal reference to a const object
Non-constant objects can be used to initialize constant references and non-constant references, but non-constant objects require type conversion to initialize constant references, and the non-constant version of the function is selected for the purpose of exact matching
6.7 Function Pointers
The function pointer points to a specific type, and the function type is determined by its return value type and formal parameter type, and has nothing to do with the function name
To declare a pointer that can point to the function, just replace the function name with the pointer, as in
Functions are automatically converted to pointers when the function name is used as a value
Directly use the pointer of only that function to call the function without dereferencing in advance
There are no conversion rules between pointers to different function types, but you can assign a value of nulllptr or 0 to a function pointer, indicating that the pointer does not point to any function
pointer to overloaded function
The compiler decides which function to use through the pointer type, and the pointer type must exactly match one of the overloaded functions
function pointer parameter
Although formal parameters of array and function types cannot be defined. But the formal parameter can be a pointer to a function
Formal parameters look like function types, but are actually used as pointers
You can directly use the function as an actual parameter, which is automatically converted to a pointer
Type aliases can be used to simplify working with pointers to functions, such as
Similar to an array, although it cannot return a function, it can return a pointer to a function type, and the return value type must be written as a pointer
Through type aliases, a symbol can be defined as a function or a pointer type to a function
Unlike the formal parameters of the function type, the return type is not automatically converted to a pointer, and the return type must be explicitly specified as a pointer
A function that returns a function pointer can be declared with a trailing return type
Use auto and decltype for function pointer pointer types
You can use decltype to simplify the function pointer return type by knowing exactly which one the return function is
When decltype is applied to a function, it returns a function type instead of a pointer type, and * needs to be explicitly added to indicate that we need to return a pointer instead of the function itself.
summary
Functions: Named units of computation, crucial to program structuring
Function contains: return type/name/parameter list/function body
Functions can be overloaded: the same name can be used to define multiple functions, as long as the parameters or types are different, the compiler will automatically select the called function
Function matching: pick the best function from a set of overloaded functions
Glossary
Ambiguous calls: when a function is matched, two or more functions provide matches that are equally good, and the compiler cannot find a single best match
Automatic objects: Objects that exist only during function execution. The object is created when the flow of program control passes through such an object definition statement and is destroyed when the end of the block in which it is defined is reached
Function prototype: function declaration contains return type/name/parameter type