Learning notes of Essential C + +, Chapter2

Posted by itazev on Tue, 18 Jan 2022 06:03:03 +0100

preface

According to the contents of Chapter 2, the second chapter mainly talks about the writing and calling of functions, which is basically the same as that of C language. Here we focus on recording what we didn't learn when learning C language. We'd better know an application scenario when we learn something. The book gives specific application scenarios to illustrate it, which is very nice.

1, Provide default parameter values

Default parameter values are provided. The specific scenario provided in the book is: for a function, whether to output the calculation process to the specified file as a parameter. If you want to calculate the process, enter the address of the file, otherwise it can be blank.
Let's take a simple example:

void try_func(int x = 0)
{
	if (x == 0) cout << "No parameters";
	else cout << 'x';
}
int main()
{
	try_func();
}

try_ The definition of func requires an integer type parameter, but it is obvious that try is not required in the main function_ Func does not provide parameters. After running the program, the output is "no parameters". Obviously, if you enter other integers, it will output 'x'.
Specific application scenario: for example, in a sorting program, the sorting program makes an error, but we don't know where the error is. At this time, we can debug or judge by observing the calculation process. To call out the calculation process, we need to enter a file address as a parameter. However, after debugging, we no longer need this process file. We set the file address parameter to null and do not output the process file, as shown in the following program

void bubble_sort(vector<int>& vec, ofstream *ofil=0)//Bubble sorting
{//Display process: ofstream type is the address of a file passed in from file output
/*Bubble sorter requires the file operations in Chapter 1*/
}
int main()
{
	int ia[8] = {9,8,7,4,6,56,2,3};
	vector<int> ia2(ia, ia + 8);//Fast assignment of vectors
	//bubble_sort(ia2);// Do not export process files
	ofstream file_p("text1.txt", ios_base::app);
	bubble_sort(ia2, &file_p);//Output process file
}

Here is the program to output the process file or not. After running, you can find the program named text1 under the project file Txt file

2, Local static object

Specific application scenario: for a frequently called function, such as Fibonacci sequence: 1, 1, 2, 3, 5... Each call will start from 1 until the required number is obtained, which increases the calculation time; Then the local static object can record this sequence in the specified function, that is, only this function records this sequence. It is impossible for the main function or other functions to call this sequence directly. This sequence can be obtained through the return value of the function. I think the biggest use is to reduce the calculation time and avoid too many variables and too many names.

const vector<int>* fibon_seq(int size)//Find Fibonacci sequence
{
	static vector<int> elems ;
	/*Program for calculating sequence
	......*/
	return &elems;//Returns the address of elems
}
int main()
{
	const vector<int> *want_seq;//important: must const
	want_seq=fibon_seq(10);//First fibon_seq
	display_address(*want_seq);
	want_seq = fibon_seq(20); cout << endl;//Second fibon_seq
	display_address(*want_seq);*/}

The key point is to use the static keyword, run the program and set a breakpoint for debugging. We will find that the second time we enter fibon_ The SEQ function does not start from the first number, but from the 12th, and it jumps out of fibon_ After the SEQ function, the elems sequence cannot be viewed.

After entering the function, elems appears in the "local variable" column, and the size is 10

3, inline function

This macro definition is similar to the C language, but this is a function version, that is, a simple replacement. Use the inline function to compare with the general calling function. According to the description of the book, the jump operation when calling the function will take a lot of time; The direct replacement of inline functions can avoid the jump operation of calling functions, but if too many inline functions are used, the code will be very large.

inline bool check_validity(int pos)
{
	return (pos <= 0 || pos > 64) ? false : true;
}

Each call to the above function is equivalent to

	if (!check_validity(size))

Become

if (!(pos <= 0 || pos > 64) ? false : true)

4, Overloaded function

Specific scenario: specific size, but different data types may require different functions, such as max_int,max_float,max_string, but there are too many functions. Then, overloaded functions can be used for functions with the same return type and different parameter types
such as

void max(int a, int b) {......}
void max(float a,float,b){......}
void max(string a,string b){......}

This is allowed, but it seems very redundant, and specific codes have to be compiled. Because there are template functions later, I don't think overloaded functions are often used

5, Template function

Overloaded functions are for functions with the same return type but different parameter lists, while template functions are for functions with different return values and parameter lists
For example, the program in the overloaded function can be written as:

template<typename mubanType>
mubanType max(mubanType a, mubanType b)
{
	return a<b?b:a;
}

This function can be called whether the data is int,float or string. It's easy to think of this application scenario: repeated code knocking for functions with different return types and parameter lists but performing the same function.

6, Function pointer

Application scenario: I have many different types of sequence: Fibonacci sequence, daffodil sequence, prime table and so on.

const vector<int>* fibon_seq(int size)//Find Fibonacci sequence
{......}

const vector<int>* prime_seq(int size)//Find prime sequence
{......}

Let's write a function to call these sequences uniformly

bool seq_elem(int pos, int& elem, const vector<int>* (*seq_ptr)(int))
{
	const vector<int>* pseq = seq_ptr(pos);

	if(!pseq)
	{
		elem = 0; return false;
	}
	elem = (*pseq)[pos-1];
	return true;
}
int main()
{
	int fibon_e;
	if (seq_elem(5, fibon_e, fibon_seq))//The fifth Fibonacci number
	cout << fibon_e;
	int fibon_e;
	if (seq_elem(5, fibon_e, prime_seq))//You want the fifth prime
	cout << fibon_e;
}

In fact, in my opinion, this is the same as calling alone. Can you write down your opinions? Or share your project experience? I hope the big guys don't hesitate to give me advice.

Topics: C++ Programming Visual Studio