Table of contents
1.1 The concept of inline function
1.3 Characteristics of inline functions
1.4 Advantages and disadvantages of macros
1.5 Technology that can replace macros in C++
2.4 Scenarios that cannot be derived by auto
3. Range-based for loop (C++11)
3.2 Conditions of use of scope for
Fourth, the pointer null value nullptr (C++11)
1. Inline functions
1.1 The concept of inline function
Inline function is a function added in C++, which can improve the efficiency of program execution. If the function is inline, the compiler will expand the inline function at the function call when compiling, so that there will be no additional overhead for the establishment of function stack frames, and the efficiency of code operation will be improved.
Inline functions can be compared to macro functions, but macro functions do not perform type checking.
#define Add(x,y) ((x)+(y))
The Add function defined by the macro, we need to pay attention to
① Did you add the type in front of x and y?
②Are parentheses added to x and y?
#define Add(x,y) (x+y)
int main()
{
int x = 1;
int ret = Add(x | 10, x & 11);
cout << ret << endl;
return 0;
}
It can be found that the calculated results do not match the expected results. Why is this happening? Because the macro function directly adds Add(x,y) at the calling place
Replaced with (x+y) --> (1|10+1&11), the priority of + is higher than | and & , so it becomes (1|11&11) in the end
So the result is not as expected
The following are parenthesized
#define Add(x,y) ((x)+(y))
int main()
{
int x = 1;
int ret = Add(x | 10, x & 11);
cout << ret << endl;
return 0;
}
③Have you added brackets as a whole?
#define Add(x,y) (x)+(y)
int main()
{
int x = 1,y = 2;
int ret = Add(x+y, x +y)*10;
cout << ret << endl;
return 0;
}
It can be found that the overall result without brackets does not match the expected result
The following are parenthesized
#define Add(x,y) ((x)+(y))
int main()
{
int x = 1,y = 2;
int ret = Add(x+y, x +y)*10;
cout << ret << endl;
return 0;
}
The result matches the expected result
According to the above macro function, we can find that a simple function requires us to pay a lot of attention. If we are not careful, there will be bugs. Obviously this is not the result we want. At the same time, macros do not support debugging, so C++ bosses The problem was discovered, so the inline function was introduced.
1.2 Use of inline functions
You only need to add a keyword inline at the front of the function, such as:
inline int Add(int x,int y)
{
return x + y;
}
The above function uses inline, and the compiler will replace the function body with the function call during compilation, which can avoid the time spent on creating unnecessary function stack frames
From the above figure, we can find that the function has not been expanded. This is because we are in debug mode at this time. In debug mode, in order to facilitate our debugging, it is not expanded by default. If it is in Release mode, the function will be expanded.
Ways to observe inline function expansion in Debug mode
Now you can observe the inline function expanded at the function call
1.3 Characteristics of inline functions
1. inline is a method of exchanging space for time . If the compiler treats the function as an inline function, it will replace the function call with the function body during the compilation phase. Defect: it may make the object file larger. Advantage: less Call overhead, improve program operating efficiency.
2. Inline is only a suggestion for the compiler . Different compilers may have different implementation mechanisms for inline. The general suggestion is: make the function smaller (that is, the function is not very long, there is no exact statement, it depends on the internal implementation of the compiler) , Functions that are not recursive and frequently called should be inline modified, otherwise the compiler will ignore the inline feature.
3. Inline does not recommend separation of declaration and definition , separation will lead to link errors. Because inline is expanded, there will be no function address, and the link will not be
found
1.4 Advantages and disadvantages of macros
(1) Advantages
① Improve code reusability
② Improve performance
(2) Disadvantages
①It is inconvenient to debug (because the preprocessing stage is replaced)
② Code readability is poor, maintainability is poor, and it is easy to misuse
③ There is no type safety check
1.5 Technology that can replace macros in C++
1. Constant definition, use const enum instead
2. Short function definition, use inline function instead
Two, the auto keyword
2.1 What is the auto keyword
The meaning of the auto keyword: thinking about type aliases
As the program becomes more and more complex, the types used in the program become more and more complex, as reflected in:
① type is difficult to spell
②The meaning of the type is not clear, which is easy to cause errors
as follows:
#include<iostream>
#include<string>
#include<vector>
int main()
{
std::vector < std::string > str;
std::vector < std::string > ::iterator it = str.begin();
return 0;
}
std::vector < std::string > ::iterator is a type. When you see this, you may think that it is not good to use typedef
#include<iostream>
#include<string>
#include<vector>
typedef std::vector < std::string > ::iterator Vi;
int main()
{
std::vector < std::string > str;
Vi it = str.begin();
return 0;
}
Although this can also be achieved, the simplification of the code, but when the typedef is used frequently, we may forget the type of our own typedef
So at this time we can use auto to directly deduce the type of it, which is convenient for viewing and writing, and it is not easy to make mistakes
#include<iostream>
#include<string>
#include<vector>
int main()
{
std::vector < std::string > str;
auto it = str.begin();
return 0;
}
2.2 Introduction to auto
①In the early C/C++, the meaning of auto is: the variable modified with auto is a local variable with automatic memory, but unfortunately no one has been
using it. You can think about why?
Because the compiler defines local variables in the function by default, and global variables defined outside the function, generally do not need to be written, so in
C++11, the standard committee gave auto a new meaning: auto is no longer a storage type indicator, but as a new type indicator to indicate to the compiler that the variable declared by auto must be deduced by the compiler at compile time.
#include<iostream>
using namespace std;
int Add(int x, int y)
{
return 1 + 2;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = 1.000;
auto a1 = Add(1,2);
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(a1).name() << endl;
return 0;
}
typeid().name() is used to deduce the variable type , the result is as follows:
② When using auto to define a variable, it must be initialized. In the compilation phase, the compiler needs to deduce the actual type of auto according to the initialization expression. Therefore, auto is not a "type" declaration, but a "placeholder" when the type is declared. The compiler will replace auto with the actual type of the variable during compilation.
int main()
{
auto a;//会报错,因为没有推导的类型
return 0;
}
2.3 Auto usage rules
1. Auto and pointers, references are used in combination
①Used in combination with pointers
#include<iostream>
using namespace std;
int main()
{
int a = 20;
auto pa=&a;
auto* pa1 = &a;
cout << pa << ' ' << pa1 << endl;
return 0;
}
At this point, it can be found that there is no difference between auto and auto*
② Auto and reference are used in combination
#include<iostream>
using namespace std;
int main()
{
int a = 20;
auto a1 = a;//表示推导类型为int,不是引用
auto& a2 = a;//表示推导类型为int&,是引用
a1 += 1;
cout << a << endl;
a2 += 1;
cout << a << endl;
return 0;
}
It can be found that if you do not add a reference, then it is simply derivation and assignment, and adding the & symbol is a reference, so if you want to quote, you cannot remove &
2. Define multiple variables on the same line
When declaring multiple variables on the same line, these variables must be of the same type, otherwise the compiler will report an error, because the compiler
actually only deduces the first type, and then defines other variables with the deduced type.
#include<iostream>
using namespace std;
int main()
{
auto a = 1, b = 2;
auto c = 'a', d = &a;//该行会报错,因为类型不同
return 0;
}
2.4 Scenarios that cannot be derived by auto
1.auto cannot be used as a function parameter
int Add(auto x,auto,y)
{
return x + y;
}
2.auto cannot be used to push to an array
int main()
{
int a[] = { 1,3,4,5 };
auto arr[] = { 1,2,3,4,5 };
return 0;
}
Note: In order to avoid confusion with auto in C++98, C++11 only retains the usage of auto as a type indicator
The most common advantage of auto in practice is the new for loop provided by C++11 , and the lambda expression is used in conjunction with it.
3. Range-based for loop (C++11)
3.1 Basic syntax of range for
In C++98, if you want to traverse an array, you can use the traditional way of writing
#include<iostream>
using namespace std;
int main()
{
int a[] = { 1,2,3,4,5 };
for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
cout << a[i] << ' ';
cout << endl;
return 0;
}
For ranged collections , it is redundant and sometimes error-prone for the programmer to specify the range of the loop. Therefore, C++11 introduces a range-based for loop. The parentheses after the for loop are divided into two parts by the colon ":", the first part is the variable used for iteration in the range, and the second part represents the range to be iterated
#include<iostream>
using namespace std;
int main()
{
int a[] = { 1,2,3,4,5 };
for (auto i : a)
cout << i << ' ';
cout << endl;
return 0;
}
Note: Similar to normal loops, you can use continue to skip this loop, and break to end the entire loop
3.2 Conditions of use of scope for
1. The range of for loop iterations must be definite
For arrays, it is the range of the elements of the first array and the elements of the last array. For classes, methods of begin and end should be provided, and begin and end are the range of for loop iterations
#include<iostream>
using namespace std;
void print(int *a)
{
for (auto i : a)
cout << i << ' ';
cout << endl;
}
int main()
{
int a[] = {1,2,3,4,5};
print(a);
return 0;
}
The above code is wrong because the scope of for is ambiguous
2. The iterator object must implement the operations of ++ and -- (the relevant content of the iterator will be updated later)
Fourth, the pointer null value nullptr (C++11)
4.1. Null pointers in C++98
In good C/C++ programming practice, when declaring a variable, it is best to give the variable an appropriate initial value, otherwise unexpected errors may occur , such as uninitialized pointers. If a pointer has no valid pointing to, we basically
initialize it as follows:
#include<iostream>
using namespace std;
int main()
{
int* p = NULL;
int* pa = 0;
return 0;
}
NULL is actually a macro. You can see the following code in the traditional C header file (stddef.h):
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
It can be seen that NULL may be defined as a literal constant 0, or it may be defined as a constant of an untyped pointer (void*). No matter what definition is used, some troubles are inevitable when using a pointer to a null value. like:
#include<iostream>
using namespace std;
void f(int)
{
cout << "f(int)" << endl;
}
void f(int*)
{
cout << "f(int*)" << endl;
}
int main()
{
f(0);
f(NULL);
f((int*)NULL);
return 0;
}
It can be found that the second call is intended to call the f(int*) function, but NULL is defined as 0, and the first function f(int) is called at this time, so it is contrary to the original intention of the program.
4.2 Precautions
In C++98, the literal constant 0 can be either an integer number or an untyped pointer (void*) constant, but the compiler treats it as an integer constant by default. To use it in pointer mode, it must be forced to (void*) 0
Note:1. When using nullptr to represent the null value of the pointer, there is no need to include the header file, because nullptr was introduced as a keyword in C++11.
2. In C++, sizeof(nullptr) and sizeof((void*)0) occupy the same number of bytes
3. In order to improve the robustness of the code, it is recommended to use nullptr when writing the code to represent the null value of the pointer
That’s all for sharing, thank you for your support, please point out any mistakes, 886!