[Lesson 3. Inline function and auto keyword and pointer null nullptr]

@C++

1. Inline function

a. Concept

"In order to solve the problem of large stack space (memory) consumption caused by some functions called many times but with a small amount of code"
1. Functions decorated with inline are called inline functions. When compiling, the C + + compiler will expand where the inline function is called, without the cost of function stack pressing

inline int Add(int left, int right)
{
	return left + right;
}

int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);//View disassembly, debug and release versions
	return 0;
}

In release mode, call Add does not exist in the assembly code generated by the compiler

	int a = 10;
	int b = 20;
	int ret = Add(a, b);//View disassembly, debug and release versions
	return 0;  

In the debug mode, call Add exists in the assembly code generated by the compiler
Because in the debug mode, it needs to be debugged by programmers, and the compiler will not optimize the code by default

	int a = 10;
00007FF7354720AB  mov         dword ptr [a],0Ah  
	int b = 20;
00007FF7354720B2  mov         dword ptr [b],14h  
	int ret = Add(a, b);//View disassembly, debug and release versions
00007FF7354720B9  mov         edx,dword ptr [b]  
00007FF7354720BC  mov         ecx,dword ptr [a]  
00007FF7354720BF  call        Add (07FF73547147Eh)  
00007FF7354720C4  mov         dword ptr [ret],eax  
	return 0;
  1. In the debug mode, the compiler will not directly expand the inline function, because in the debug mode, the user needs to debug the code.

b. Characteristics

i. inline is a method of exchanging space for time

At the cost of code replication, it only saves the cost of function call, so as to improve the efficiency of function execution. Therefore = if the code is very long or there is a circular / recursive function, and the cost of copying is greater than that of calling, it is not suitable to use it as an inline function
(1) The code in the function is very long. Using inline will lead to high cost of function consumption
(2) If loop / recursion occurs in the function body, the time to execute the code in the function body is more expensive than the function call

ii. inline is just a suggestion for the compiler

We have declared the inline function, and the compiler will automatically optimize it. The function defined as inline has loops / recursion in its body. The function is complex, and the compiler will ignore the inline. If the calling function is not complex, expand it at the calling place and execute the inline function.

iii. inline does not recommend separation of declaration and definition

Separation can lead to link errors. Because the inline is expanded, there will be no function address, and the link will not be found.

2. auto keyword (C++11)

a. Introduction to auto

i. auto is no longer a storage type indicator. Instead, as a new type indicator to instruct the compiler, the variables declared by auto must be derived by the compiler at compile time.

int main()
{
   auto a = 10;//When writing code, auto is a placeholder
   auto b = 12.3;
   auto c = 'c';
   cout << typeid(a).name()<< endl;
   cout << typeid(b).name()<< endl;
   cout << typeid(c).name() << endl;
   return 0;
}
int
double
char

Note: when using auto to define variables, it must be initialized. In the compilation stage, 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" for type declaration. The compiler will replace Auto with the actual type of variable at compile time.

b. Usage rules of Auto

i. auto is used in conjunction with pointers and references

int a=12;
auto* pa=&a;//When auto declares pointer variables, there is no difference between auto and auto *
auto pa=&a;

auto& ra=a;//auto life reference type must be added&

ii. Define multiple variables on the same line

int main()
{
	auto a = 12, b = 34, c = 56;
	auto a = 12, b = 1.2, c = 'c';//Compilation failed
	return 0;
}

Why should variables be of the same type when declaring the same row of variables?
Because the compiler actually only deduces the first type, and then defines other variables with the pushed type

c. Scenes that cannot be deduced by auto

i. auto cannot be an argument to a function

ii. auto cannot be used directly to declare arrays

3. Range based for loop (C++11)

a. Syntax for scope

For an array with a range, it is unnecessary for the programmer to explain the range.
Therefore, in C++11, a range based for loop is introduced

int main()
{
	int array[] = { 1,2,3,4,5,6,7,8,9,0 };
	//e is a copy of each element of the array
	for (auto e : array)//C + + range for loop
		cout << e << " ";
	cout << endl;
	/*
	int* p = array; //A pointer cannot be used to represent the range in which an array is iterated
	for (auto e : p)//int *The scope of is not specific -- the compiler cannot determine the scope represented by p at the compile time
	*/
	//e is the alias of each element of array
	for (auto& e : array)
		cout << e << " ";
	cout << endl;
	return 0;
}
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0

b. Conditions for use of the scope

The scope of the range for iteration must be determined. If the pointer is used instead of the array, the iteration scope cannot be determined. (code above)

4. Null pointer nullptr

Pointer null value in C++98

NULL is actually a macro. In the traditional c header file, < stdio h>

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

The constant (void *) can be defined as NULL, and the constant (void *) can also be defined as NULL

void Test(int* a)
{
	cout << "Test(int* a)" << endl;
}
void Test(int a)
{
	cout << "Test(int a)" << endl;
}
int main()
{
	int a = 1;
	int* b = &a;
	int* pd = NULL;//NULL indicates a NULL pointer
	Test(a);
	Test(b);
	Test(pd);
	Test(NULL);
	Test((int*)NULL);//NULL indicates a NULL pointer. Test (int) should be called*
	Test(0);

	int* pc = nullptr;//Null pointer: (void *) pointer to 0
	Test(pc);
	Test(nullptr);
	return 0;
}
Test(int a)
Test(int* a)
Test(int* a)
Test(int a)
Test(int* a)
Test(int a)
Test(int* a)
Test(int* a)

Call the pointer version of f((int *)) function through f(NULL), but since NULL is defined as 0, it is contrary to the program.
In C++11, nullptr represents the pointer of null value (void *)0.

be careful:

  1. When nullptr is used to represent pointer null value, it is not necessary to include header file, because nullptr is introduced by C++11 as a new keyword.
  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 in the subsequent representation of pointer null values.

Tags: C++

Posted by Calamity-Clare on Mon, 18 Apr 2022 21:35:54 +0930