inline function and auto keyword and nullptr [c++]

Table of contents

1. Introverted function

 How to observe whether a function is expanded

inline features

Two, the auto keyword

Rules for using the auto keyword

Three, the pointer null value nullptr (c++11)


 

 

1. Introverted function

A function call needs to build a function stack, and every time a function is called, a stack needs to be built and destroyed. Although the overhead of such a process is not particularly large, when you need to call a function multiple times in a program, this is a big deal. expenses. In fact, there is already a solution in the c language: macro functions. as follows:

#define ADD(x,y) ((x)+(y))

 C++ has its own solution, instead of using the macro function in C language, why is this?

Macro functions have some drawbacks:

  1. Most importantly, it is easy to make mistakes. Questions of priority are often involved
  2. There is no type safety check. For example, you will use the x and y above without judging what type of data it is.
  3. Cannot be debugged (the program will be replaced directly during precompilation, so it cannot be debugged)

The c++ solution will not have another problem, the introverted function:

A function decorated with inline is called an inline function. When compiling, the C++ compiler will expand it at the place where the inline function is called . There is no overhead of creating a stack frame for function calls. Inline functions improve the efficiency of program operation.

His specific role is like the following code:

b2f2830505cc4dd18526cd847cde72c7.png

Become as follows, but this is just an image representation

int main()
{
	int x = 10, y = 10;
	int ret = add(x, y)
	{
		return x + y;
	}
	return 0;
}

 How to observe whether a function is expanded

1. Check in the release and mode, whether the assembly language generated by the compiler calls add again, if so, it means that the add function is called and a stack is generated.

2. To view in debug mode, some settings need to be made, because debug mode is a debugging mode, if the function is expanded, the inline function cannot be debugged.

In vs2022, the following settings can be used to enable the program to be expanded in debug mode.

d107524c296c44639463a98f42ba1474.png

as well as928acaed0010434c9fe6bf546aceb430.png 

 Then we observe his assembly language and we can find that the function is not called here, but the instruction is directly executed here:

e29248f8be3447f68fbc76f687033123.png

inline features

1. inline is a way 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. It is reflected in the fact that expanding the function will increase the code size of the function, which directly affects the size of the executable file (.exe).

Why do you say that the compiler treats the function as an inline function, because whether the inline function you declare is expanded is ultimately determined by your compiler. Because if you define a recursive function or a function with dozens or hundreds of lines, it will be very unreasonable for the compiler to expand every time it encounters one. Reasonable.

2. Inline is just 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, and 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.        

321c9b7312aa4bd08944a26b59464b06.png

 3. Inline does not recommend separation of declaration and definition, separation will lead to link errors. Because inline is expanded, there is no function address (because there is no need to find the address of the function), and the link will not be found.

 

Two, the auto keyword

As the program becomes more and more complex, the data types used in the program become more and more complex, which is reflected in:

1. Types are hard to spell

2. Unclear meaning leads to errors

for example:

std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange", "橙子" }, 
   {"pear","梨"} };
 std::map<std::string, std::string>::iterator it = m.begin();

This is a data type with a very complicated name. At this time, we can use the auto keyword to solve this embarrassing problem.

The function of auto is to automatically identify the type, and the usage is as follows:

int x;
auto e=x;

In this piece of code, auto e automatically recognizes that x is of type int, and declares a space of type int for e.

Rules for using the auto keyword

1. Auto is used in combination with pointers and references :

There is no difference between using auto and auto* when declaring data of pointer type. But the combination of auto and reference is different.

int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;//这里就相当于int &c=x;
    cout << typeid(a).name() << endl;//这里的作用是将括号内的数据类型打印出来。
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    *a = 20;
    *b = 30;
     c = 40;
    return 0;
}

43450c4116bf4caf9843cf97bdf08630.png

 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 only deduces the first variable, and then defines other variables of the deduced type.

void TestAuto()
{
    auto a = 1, b = 2; 
    auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

3. Scenarios where auto cannot be derived

(1). .auto cannot be used as a function parameter

void TestAuto(auto a)
{}

Because a stack needs to be built when the function is called, the type defined by auto cannot determine its size, and the size of the built stack may not be enough to hold this variable.

(2) auto cannot usher in the declared array

void TestAuto()
{
    int a[]={1,2,3};
    auto b[]={4,5,6};
}

Three, the pointer null value nullptr (c++11)

The pointer definition in c/c++98 is flawed. The c++ committee did not correct this flaw for language compatibility in subsequent c++ versions. Instead, it patched the grammar and added nullptr. The defects are as follows:

NULL is actually a macro. In the traditional c header file (stddef.h), you can see the following code:

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif
As you can see, NULL may be defined as the literal constant 0 , or as a constant of an untyped pointer (void*) . no matter what
This kind of definition, when using the pointer of null value, will inevitably encounter some troubles, such as:
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; 
}

Although there is syntax overloading, which function should be called?

aaec4f4dd25f4a69a787929524d3ac69.png

The original purpose of the program is to call the pointer version of the f(int*) function through f(NULL), but since NULL is defined as 0, it is different from the program's
Contrary to the original intention.

 

Notice:
1. When using nullptr to represent the null value of the pointer, there is no need to include the header file, because nullptr is introduced as a new keyword in C++11
of .
2. In C++11 , 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 representing the null value of the pointer .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_64484137/article/details/126960172