C++primer Chapter 6 Functions

Chapter 6 Functions

  • 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
      1. Initialize the formal parameters corresponding to the function with actual parameters
      1. transfer control to the called function
    • The execution of the calling function is interrupted, and the called function starts executing
    • return statement:
        1. returns the value in the return statement
        1. 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
void print(int (*matrix)[10],int rowSize){
    
    ...}//matrix指向含有10个整数的数组的指针
void print(int matrix[][10],int rowSize){
    
    ...}//与上式等价

6.2.5 main: processing command line options

//argc表示数组中字符串的数量 argv是一个数组它的元素是指向C风格字符串的指针
int main(int argc,char *argv[]){
    
    ...}
//与上式等效 其中argv指向cahr* argv的第一个元素指向程序的名字或者一个空字符串
//接下来的元素依次传递命令行提供的实参 最后一个指针之后的元素值保证为0
int main(int argc,char **argv){
    
    ...}

6.2.6 Functions with variable parameters

  • 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
      1. 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
      1. Matches achieved by const conversions
      1. Matching of type promotion implementations
      1. Arithmetic type conversion/pointer conversion
      1. 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
bool (*pf)(const string&,const string&);
//pf前有一个*,故pf为指针,右侧为形参列表,表示pf指向的是函数,左侧函数返回值是布尔值
//pf指向一个形参是两个const string的引用,返回类型是bool的函数
//*pf两端的括号不可少,不加括号的话则pf是一个返回值为bool指针的函数
  • using function pointers
    • 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
//Func和Func2是函数类型
//调用Func作为参数时编译器自动将Func表示的函数类型转换为指针
typedef bool Func(const string&,const string&);
typedef decltype(lengthCompare) Func2;//与上式等价
//FuncP和FuncP2是指向函数的指针
typedef bool (*FuncP)(const string&,const string&);
typedef decltype(lengthCompare) *FuncP2;//与上式等价
//decltype返回函数类型,不会自动将函数类型转换为指针类型,只有在结果前面加*才能得到指针
  • return pointer to function
    • 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

Guess you like

Origin blog.csdn.net/m0_68312479/article/details/128603726