Article Directory
function overloading
Functions with the same name are defined at the same scope, but their parameters are distinguished, and the relationship between such functions is called function overload.
Function overload matching
When a function of an overload relationship is called, the compiler automatically selects the optimal overload version based on the degree of match between the arguments and the shape parameters.
General rules for current g++ compiler matching:
Exact Match >=Constant Conversion > Upgrade Conversion > Downgrade Conversion > Ellipsis
Principle of Function Overload
The C++ compiler resolves the conflict between function overload and name conflict by exchanging functions and integrating the type information of parameter tables into new names.
Use the keyword "extern" to declare a function in C++, requiring that the function not be renamed to facilitate C program calls to the function.
Code Samples
- overload.cpp
#include <iostream> using namespace std; int foo(int i){ cout << "foo(int)" << endl; } void foo(int i,int j){ cout << "foo(int,int)" << endl; } void foo(int a,float f){ cout << "foo(int,float)" << endl; } int main(void) { foo(10); foo(10,20); foo(10,1.23f); /*The type of function pointer determines its matching version*/ void (*pfoo)(int,float) = foo; pfoo(10,20); return 0; }
- results of enforcement
- 02overload.cpp
#include <iostream> using namespace std; //Char->int: Upgrade Conversion void bar(int i){ cout << "bar(1)" << endl; } //Char->const char:*Constant conversion* void bar(const char c){ cout << "bar(2)" << endl; } //Short->char: downgrade conversion void func(char c){ cout << "func(1)" << endl; } //Short->int: upgrade conversion void func(int i){ cout << "func(2)" << endl; } //Ellipsis Matching (Worst) void hum(int i,...){ cout << "hum(1)" << endl; } //Double->int: downgrade conversion void hum(int i,int j){ cout << "hum(2)" << endl; } int main(void) { char c = 'a'; bar(c); short s = 10; func(s); hum(10,1.23); return 0; }
- results of enforcement
Default parameter for a function (default argument)
- You can specify a default value for some or all of the parameters of a function, which can be used as the corresponding argument value when the function is called if no arguments are passed.
void func(int a,int b,int flag=0){}
- On the right side, if a parameter of a function has a default value, then all parameters to the right of the parameter must have default values.
void func(int a = 0,int b){}//error void func(int b,int a = 0){}//ok
- If the definition and declaration of a function are separate, the default parameters should be written in the declaration part of the function, but not in the definition part.
void func(int a = Default value);//Function declaration void func(int a){...};//Function Definition
Code Samples
- defarg.cpp
#include <iostream> using namespace std; //Function declaration void foo(int a,int b = 200,int c = 300); int main(void) { foo(10);//10,200,300 foo(10,20);//10,20,300 foo(10,20,30);//10,20,30 return 0; } //Function Definition void foo(int a,int b/*=200*/,int c/*=300*/){ cout << a << ',' << b << ',' << c << endl; }
- results of enforcement
Dummy function
- Parameters that have only a type but no variable name become Dummies
void func(int/*Dummy element*/){...}
- Scenes using Dummies
- Operator overload, distinguish before and after ++/- -
- To be compatible with old code
Code Samples
- 02defarg.cpp
#include <iostream> using namespace std; //Function declaration void foo(int a,int=0/*Dummy element*/); int main(void) { foo(10);//10,200,300 foo(10,20);//10,20,300 foo(10,20,30);//10,20,30 return 0; } //Function Definition void foo(int a,int=0){ cout << "a = " << a << endl; }
- results of enforcement
inline function
- The function decorated with inline keyword means that it is an inline function. The compiler optimizes common sense inline to avoid the overhead of function invocation and improve the efficiency of program execution.
- Explain:
- Small, simple functions called multiple times are suitable for inlining.
- Functions that are rarely called or that are large and complex are not suitable for inlining.
- Recursive functions cannot be optimized inline.
- Note: Inline is only a recommendation, not a mandatory requirement. Whether a function can be optimized inline depends on the compiler. Some functions are treated as inline optimization by default without inline modification. Some functions are ignored by the compiler even with inline modification.
Dynamic memory allocation in C++.
Previous use of dynamic memory allocation in C language:
- Allocation (malloc())
- Release (free())
- Error handling (error handling based on return values)
Now C++ uses operators for dynamic memory management
- Allocation: new, new[]
- Release: delete, delete[]
- Error handling: C++ exception mechanism
Code Samples
- new.cpp
#include <iostream> using namespace std; int main(void) { int* pi = new int; *pi = 123; cout << *pi << endl; delete pi;//Prevent memory leaks pi = NULL;//Avoid Field Pointer //new memory initialization at the same time int* p2 = new int(321); cout << *p2 << endl;//321 delete p2; p2 = NULL; //new array, containing 10 elements int* pa = new int[10]; for(int i=0;i<10;i++){ pa[i] = i; cout << pa[i] << ' '; } cout << endl; delete[] pa; pa = NULL; //new array, initialized at the same time, requires C++11 standard support int* pa2 = new int[10]{9,8,7,6,5,4,3,2,1,0}; for(int i=0;i<10;i++){ cout << pa2[i] << ' '; } cout << endl; delete[] pa2; pa2 = NULL; return 0; }
- results of enforcement
reference
Definition
- A reference is an alias for a variable and operates exactly the same as the variable itself.
- grammar
type & Reference Name = Variable Name; //Note: References must be initialized when they are defined, and the target bound after initialization cannot be modified. //Note: The type of reference should be the same as the type of target variable it binds to eg: int a = 10; int& b = a;//b is the alias of a b++; cout << a << endl;//11 int c = 20; b = c;//Assignment, not the target of changing references cout << a << endl;//20
Frequently cited
- Definition references are const-modified, that is, they are frequent references and cannot modify the target of references through frequent references.
int a = 10; const int& b = a;//b is a common reference to a //Int const&b = a; //and above equivalent
- Ordinary references can also be referred to as left-value references and can only refer to left-value references. Ordinary references can also be referred to as universal references, which can refer to both left-value and right-value references.
- About left and right values
Lvalue: can be placed to the left of the assignment operator and can be modified -->Non-const common variables are left values Rvalue: can only be placed to the right of the assignment operator and cannot be modified -->Constant -->Temporary Variables int a = 100; //a(int)-->tmp(double) double& r = a;//error int& r = 100;//error
Referential function parameters
- References are used for function parameters, in which case the parameter is an alias for the parameter, which can directly modify the value of the parameter variable, while avoiding the parameter value transfer process and improving code execution efficiency.
- Reference parameters may accidentally modify the value of an argument. If you do not want to modify the argument variable itself, you can define the parameter as a constant reference, which improves the efficiency of the parameter transfer while also accepting constant arguments.
Code Samples
- reference.cpp
#include <iostream> using namespace std; int main(void) { int a = 66; int& b = a;//b refers to a,b is the alias of a cout << "&a=" << &a << endl; cout << "&b=" << &b << endl; b++; cout << "a=" << a << endl;//67 cout << "b=" << b << endl;//67 //int& r;//error //double& r = a;//error }
- results of enforcement
- constref.cpp
#include <iostream> using namespace std; int func(void){ int num = 123; //Compilation generates a temporary variable to hold return data return num;//int tmp=num } int main(void) { //The function returns a temporary variable (right value), a common reference //Can't receive, often referenced can //int res = tmp; //int& res = func();//error const int& res = func();//ok cout << res << endl;//123 //100 is a constant (right value), ordinary references cannot refer to right values //int& ri = 100;//error //Frequent references can refer to right values const int& ri = 100;//ok int i = 200; //i is a left value, but needs to be initialized for double type rd //Implicit conversion is done first, and the result is saved to a //Temporary variables are all right values, so error //double& rd = i;//error //rd actually refers to a temporary variable, not i itself const double& rd = i; cout << "&i=" << &i << endl; cout << "&rd=" << &rd << endl; return 0; }
- results of enforcement
- refArg.cpp
#include <iostream> using namespace std; /*void swap1(int* x,int* y){ *x = *x ^ *y;//011 ^ 101 = 110(x) *y = *x ^ *y;//110 ^ 101 = 011(y)->3 *x = *x ^ *y;//110 ^ 011 = 101(x)->5 }*/ void swap2(int& x,int& y){ x = x ^ y; y = x ^ y; x = x ^ y; } int main(void) { int a = 3,b = 5; //swap1(&a,&b); swap2(a,b); //a=5,b=3 cout << "a=" << a << ",b=" << b << endl; return 0; }
-
results of enforcement
-
02refArg.cpp
#include <iostream> using namespace std; struct Student{ char name[128]; int age; int no; }; void print(const Student& s){ cout << "My name is" << s.name << ",This year" << s.age/*++*/ <<"year,The number is" << s.no << endl; } int main(void) { const Student stu = {"King",45,10086}; print(stu); print(stu); print(stu); return 0; }
- results of enforcement