- A function is a named block of code that executes code by calling the function.
- A function may have zero or more arguments and may produce zero or one result.
- Functions can be overloaded, meaning that one name corresponds to multiple different functions.
Basis function
- The argument is the initial value of the parameter. They correspond one to one. The parameter type must match or be converted. But the call operator does not specify the order in which the arguments are evaluated.
- For compatibility with C, the void keyword is used to indicate that the function has no parameters.
- Each parameter is a declaration containing a descriptor. But even if two parameters are of the same type, they must both be typed and cannot be omitted.
- A local variable in the outermost scope of a function cannot have the same name as a parameter.
- Parameter names are optional. Parameters that will not be used need not be named, but must provide arguments.
- The return type of a function cannot be an array or function type, but can be a pointer to an array or function.
Local objects
- Automatic objects: Objects that exist only during block execution
- A parameter is an automatic object that is created at the start of a function and destroyed at its termination
- If the automatic object definition corresponding to a local variable has an initial value, the local variable is initialized with the initial value. If there is no initial value, the local variable is initialized by default. That is, an uninitialized local variable of a built-in type yields an undefined value.
- Local static objects: Local variables are defined as static, initialized when the program executes the first defined statement, and destroyed until the program terminates.
- If a local static object does not have an explicit initialization value, value initialization is performed. That is, local static variables of built-in types are initialized to 0
Function declaration
- The name of the function must be declared before use. Functions can only be defined once, but can be declared more than once. If a function will not be used, it can be declared without definition.
- A function declaration is also called a function prototype. The three elements of a function declaration (return type, function name, parameter type) describe the interface of the function.
- Function declarations do not require a function body. use a semicolon instead. Parameters in the declaration are not named because they are not used.
- It is recommended that functions be declared in header files and defined in source files. Same as variables.
Separate compilation
- C++ supports split compilation, which allows you to split a program into several files and compile each file separately.
- Each file generates a suffix name when compiled separately
.obj(windows)
or.o(UNIX)
, meaning that the file contains object code - Compiled separately
The linker
Link object files together to become executable files
Parameter passing
- The parameters are recreated and initialized with arguments each time the function is called
- If the parameter is a reference type, it is bound to the corresponding argument; otherwise, the value of the argument is copied to the parameter.
- Two kinds of parameters:
reference
The: parameter is a reference type. The reference parameter is bound to the object corresponding to the argument and is the alias of the argument. Say such arguments are passed by reference, or that the function is called by reference.Value passed
The value of the argument is copied to the parameter. The parameter and the argument are two separate objects. Say that such arguments are passed by value, or that the function is called by value
- C programmers often modify objects outside functions with pointer type parameters, but in C++ it is recommended to replace Pointers with reference type parameters
Reference parameter passing
- When passing parameters by reference:
- Copying objects of large class types or containers is inefficient and is best accessed by reference parameters
- Some types (such as IO classes) cannot be copied and can only be accessed by reference
- Pass a reference to a function
Returns multiple results at once
Provides a way to modify a function by passing multiple objects as references. - Best used when reference parameters do not need to be modified
Const reference
Array parameter
- Cannot copy array, so
Cannot be passed by value
The incoming array - Since arrays are converted to Pointers, passing an array to a function is actually
The pointer
. So inside the functionCan't use sizeof
Array size, etc.) - The size of the parameter group has no effect on the function
I don't know
The size of the real parameter group
Const int * void print(const int *); const int * void print(const int *); void print(const int []); void print(const int [10]); // Array sizes are discarded when passed inCopy the code
- There are three ways to scope an array:
- Require the array itself to have an end tag, such as a C-style string
- We pass in a pair of iterators (leading and trailing Pointers), which can be obtained by the begin and end functions, similar to library operations
- Defines a parameter that represents the size of an array
Void print(const int *beg, const int *end){} void print(const int *beg, const int *end){} Size_t size){} // Pass in the sizeCopy the code
- If the function does not write to an array element, the array parameter should be a pointer to const
- The parameter can be
Array reference
In this case, the reference parameter is bound to the corresponding array. In this case, the array is prevented from being converted into a pointer. The size of the argument must be the same as that of the parameter. - Example: The parameter is a reference to an array, which does not convert Pointers
Void print(int (&arr)[10]){for(auto elem:arr) cout<<elem<<endl; for(auto elem:arr) cout<<elem<<endl; }Copy the code
- When passing a multidimensional array, the first element of the multidimensional array is itself an array, so the first element pointer is a pointer to the array. When a function is passed in, the object to which the first pointer points is still an array, so the size of the second dimension and all subsequent dimensions of the array are part of the array type and cannot be omitted.
Return type and return statement
- The return statement terminates the currently executing function and returns control to the place where the function was called
Functions with and without return values
- As long as the function return type is not void, every return within the function must return a value. The return type must be the same as the function return type, or can be implicitly converted to the function return type
- A function that returns a value must return with an explicit return, and there is no implicit return. A return without an explicit return is undefined.
- A function returns a value in the same way it initializes a variable or parameter: the returned value is used to initialize a temporary quantity of the call point that is the result of the call to the expression
- If the return value is not referenced, it is copied to the point of call. If the return value is a reference, it is simply the alias of the object it quotes.
Cannot return a reference or pointer to a local object
Function termination means that a reference to a local variable will point to a memory region that is no longer valid.- Call operator
(a)
The priority and dot operators of.
And arrow operators->
Same, and satisfies the left associative property. Therefore, if the function returns an object of class type or a reference to it, the member can be fetched directly after the expression is called
Return array pointer
- An array cannot be copied, so the function cannot return an array, but it can return a pointer or reference to the array
- If you do not use a type alias, you must remember to include the array dimension. To define a function that returns an array pointer, the dimension of the returned array must be placed after the parameter list. Like:
type (*function(parameter_list))[dimension]
. Read: function is a function with parameter_list. It returns a pointer to an array of dimension and element type type - Trailing return types: To simplify the definition of complex return types, any function definition can use trailing returns. The trailing return type is placed after the parameter list and begins with ->, using auto instead of the original return type. Tail returns a function commonly used to return an array pointer or reference
- If you know which array the pointer to the function returns points to
decltype
Declare the return type. Decltype does not convert Pointers to arrays, so pointer symbols must be added manually
typedef int arrT[10]; Using arrT=int[10]; ArrT *func(int I); arrT *func(int I); Int odd[]={1,3,5,7,9}; Int even [] =,2,4,6,8 {0}; Decltype (odd) *arrPtr(int I){return (I %2)? Decltype (odd) *arrPtr(int I){ (&odd):(&even); }Copy the code
Function overloading
- Overloaded functions: Several functions in the same scope have the same name but different parameter lists. That is, there should be a distinction between the number or type of parameters (just returning different types is not overloading).
- When an overloaded function is called, the compiler infers which function it wants based on the argument type
- The main function cannot be overloaded
- The top-level const does not affect the object passed into the function,
Top-level const parameters are indistinguishable from top-level nonconst parameters, so top-level const cannot be overloaded
- If the parameter is a pointer or reference, overloading can be achieved by distinguishing whether the pointing object is const, i.e
Underlying const can be overloaded
Record lookup(Phone); Record lookup(const Phone); Record lookup(Phone *); Record lookup(Phone *); Record lookup(Phone * const); Record lookup(Account &); Record lookup(Account &); Record lookup(const Account &); Record lookup(Account *); Record lookup(Account *); Record lookup(const Account *); // The underlying const can be overriddenCopy the code
- The compiler can determine which function to call based on whether the underlying argument is const.
- Const objects/Pointers to const can only be passed to the underlying const parameter
- Nonconst objects/Pointers to nonconst can be passed to either the underlying const parameter or the underlying nonconst parameter, but the compiler preferentially selects the underlying nonconst version
- Const_cast is useful in the case of overloaded functions, where it can modify the underlying const permissions of Pointers or references. If a reference to a nonconstant object is declared as a constant reference to a pointer to a constant, then the object cannot be modified by the reference, unless the underlying const qualification is removed by const_cast.
- The underlying const of a reference/pointer can be removed only if the underlying object is a nonconstant
- Example: const_cast modifies the underlying const of a reference/pointer
ShorterString (const string&s1, const string&s2){return (s1.size()<=s2.size()>)? (s1):(s2); } // An overload of the previous function, Both input and output are versions of non-constant references string &shorterString(string &s1, String &s2){// The input object is originally non-constant auto &r=shorterString(const_cast<const string &>(s1), const_cast<const string &>(s2)); // Change the reference permission to the underlying const return const_cast<string &>(r); // The underlying object is still very large, but the reference is the underlying const, and can be changed by const_cast}Copy the code
- There are three possible results when an overloaded function is called:
- Find the function that best matches
- No function can be found to match the argument, no matching error
- Matches more than one function, but each one is not optimal, ambiguous call error
Special purpose language features
The default argument
- Default argument: a function can be called without specifying the corresponding parameter, which is initialized as the default argument.
- A parameter with default arguments that can either accept default arguments or be assigned a specified value when called
- Default arguments are only at the end of the parameter list: arguments are resolved by position during a function call, and default arguments are responsible for filling in missing tail arguments in a function call
- When designing functions that have default arguments, you need to arrange the parameters in a reasonable order
string screen(sz, sz, char=' '); String screen(sz, sz, char='*'); String screen(sz=24, sz=80, char); // Yes, add default argumentsCopy the code
- Local variables within a function cannot be used as default arguments
- Names used as default arguments are resolved in the scope in which the function is declared, but evaluation occurs when the function is called
- Example: The name of the default argument is resolved in the declaration scope, but evaluation occurs at call time
sz wd=80; char def=' '; sz ht(); string screen(sz=ht(), sz=wd, char=def); // Declare a function with a default argument string window=screen(); //screen(ht(),80,' ') void f2(){ def='*'; //def is still external sz wd=100; · window=screen(); // The name of the default argument is resolved externally, so it is screen(ht(),80,'*')}Copy the code
Inline functions and CONSTexpr
- Calling a function is slower than evaluating an equivalent expression because of the overhead of running the function
Inline function
: Expands the function inline at each call point (similar to macro definition) to avoid runtime overhead. The form is appended to the return type of the functioninline
The keyword- Inline instructions are simply requests to the compiler, which can ignore them
- Inlining works fine
Small scale, direct flow, frequent invocation
The function. Many compilers do not support inline recursive functions Constexpr function
: a function that can be used in a constant expression, whose return type and argument types are literals, and whose bodyThere is and only one return statement
- A constexpr function should be determinable at compile time and return a value of
Constant expression
, so we can assign values to constEXPr variables. - To expand at compile time,
Constexpr must be inline
the - allow
The return value of constExpr is non-constant
As long as you make sureInput constant expression
When canOutput constant expression
(i.e.Evaluate at compile time
).
constexpr int new_sz() {return 42; } // Return the constant expression constexpr size_t scale(size_t CNT) {return new_sz()* CNT; Int arr[scale(2)]; Int I =2; int I =2; int a2[scale(i)]; The scale input is not a constant expression, and the output is not a constant expressionCopy the code
- Normal functions can be declared multiple times but not defined multiple times (don’t put the definition of a normal function in a header file), but inline functions and constexpr functions can be defined multiple times, as long as the definitions are the same. Because calling these functions is just an inline expansion
- Inline functions and constEXPr functions should be defined in header files. Since an inline function is expanded at compile time (before linking), its definition must be visible to the compiler
Debugging help
- The assert macro uses expressions as conditions, in the form of Assert (expr). Evaluate expr, if true do nothing, if false print information and terminate the program
- Preprocessing names are managed by the preprocessor, not the compiler, and are not in the STD namespace. They must be unique within the program.
- The assert macro’s behavior depends on the preprocessing variable NDEBUG, and if NDEBUG is defined, the assert macro does nothing.
- NDEBUG is not defined by default. Use #define NDEBUG to define it to turn off the debug state and not perform assert checks
- Preprocessing variables can also be specified in the compile option
__func__
The compiler defines this variable for each function, which is a static array of const char that holds the function name- The preprocessor defines several other names that are useful for debugging:
__FILE__
The string literal that holds the filename__LINE__
An integer literal that holds the current line number__TIME__
The string literal that holds the compile time of the file__DATE__
The string literal that holds the compile date of the file
Function matching
- Function matching is difficult when several overloaded functions have the same number of parameters and some parameter types can be converted
- Step 1: Filter by name. Requirements: 1. Be the same as the function being called; 2. Visible at the call point. These functions are called candidate functions
- Step 2: Filter by argument. Requirements: 1. The form participates in the number of arguments matching; Parameters can be converted to parameters. These functions are called viable functions, and if there are no viable functions, the compiler reports an error: no matching function
- Step 3: Choose the best match. The closer the type of the real participating parameter is, the better the match is, and an exact match is better than one that requires a type conversion.
- When selecting the best match, the match succeeds if there is one and only one function that meets the following criteria, otherwise the compiler will report an error:
- The match of each argument to this function is no worse than that of the other feasible functions
- The function has at least one argument that matches better than the other viable functions
- Avoid casting when calling overloaded functions. Arguments should not be cast in a well-designed system
Argument type matching conversion
- To determine the best match, the compiler classifies the argument to parameter conversion into several levels:
- Exact matching, including: same type, array to pointer, function to pointer, change top-level const
- A match through a const conversion
- Matching through type promotion
- A match by arithmetic conversion or pointer conversion
- A match through a class type conversion
- Even small integers are directly promoted to int
- At the same level as all arithmetic conversions, double to float is no better than double to int.
- A nonconstant object initializing a constant reference requires a type conversion
- Example: argument type conversion
Void ff(int); void ff(short); ff('a'); // void manip(long); // void manip(long); void manip(float); Manip (3.14); Record lookup(Account &); Record lookup(Account &); Record lookup(Account &); Record lookup(const Account &); const Account a; Account b; lookup(a); Call (const Account &) lookup(b); // The underlying nonconst matches the underlying nonconst first, calling (Account &)Copy the code
A function pointer
- The function pointer points to
function
Not objects.Functions are not objects
- The type of the function depends on it
Return value type
andParameter type
Jointly determined, regardless of function and parameter names. - When a function name is used as a value, the function is automatically converted to a pointer
- A function can be called using a function pointer without writing and dereferencing
*
It doesn’t matter - Example: function types and function Pointers
bool lengthCompare(const string &, const string &); // The type is bool(const string&, const string&) bool(*pf)(const string&, const string&); Pf =&lengthCompare; Pf =lengthCompare; // This is equivalent to the previous statement. Bool b1=pf("hello","goodbye"); bool b1=pf("hello","goodbye"); // The dereference is optional bool b2=(*pf)("hello","goodbye"); bool b3=lengthCompare("hello","goodbye");Copy the code
- There are no conversion rules between Pointers to different function types
- A constant expression that can assign a function pointer to nullptr or 0 to indicate that it does not point to any function
- If a pointer to an overloaded function is defined, the pointer type must match exactly one of the functions
- Example: Pointers to overloaded functions must match exactly
void ff(int *); void ff(unsigned int); void (*pf1)(unsigned int)=ff; Ff (unsigned int) void (*pf2)(int)=ff; Void (*pf3)(int *)=ff; // No exact matchCopy the code
- A parameter of a function type cannot be defined, but a parameter can be a pointer to a function. This looks like a function, but is actually a pointer. Functions in parameters are automatically converted to Pointers
- Function prototypes that use type aliases and decltype simplified functions/function Pointers as parameters. Functions that do decltype are not converted to Pointers
- Example: Parameters are Pointers to functions
Bool lengthCompare(const string &, const string &); Void useBigger(const string&s1, const string&s2, bool pf(const string&, const string&)); void useBigger( const string &s1, const string &s2, bool (*pf)(const string &, const string &)); // Typepedef bool Func(const string &, const string &); typedef decltype(lengthCompare) Func; // The following two lines are equivalent; FuncP is a function pointer typedef bool (*FuncP)(const string &, const string &); typedef decltype(lengthCompare) *FuncP; Void useBigger(const string&s1, const string&s2, Func); void useBigger(const string &s1, const string &s2, FuncP);Copy the code
- You cannot use a function as a return value, but you can use a function pointer as a return value
- When a function pointer is returned, it must be explicitly written as a pointer. Function types in return values are not automatically converted to Pointers
- You can use a type alias and a trailing return type simplified function pointer as a function prototype for the return value
- Example: The return type is a function pointer
using F=int(int*,int); Using PF=int(*)(int*,int); Int (*f1(int))(int*,int); // declare PF f1(int); // Return a pointer to the function, equivalent to the previous line F *f1(int); // Return a pointer to the function, equivalent to the previous line F f1(int); Auto f1(int) -> int(*)(int*,int); // This is equivalent to the original declarationCopy the code
- Auto and decltype can also be used to return prototypes of function Pointers
- Example: decltype is used to return a function pointer
string::size_type sumLength(const string &, const string &); string::size_type largerLength(const string &, const string &); decltype(sumLength) *getFcn(const string &); // Returns a pointer to one of the above two functionsCopy the code