Chapter 3 of learning notes of Essential C + +: generic programming style

Posted by dicky18 on Wed, 19 Jan 2022 20:25:07 +0100

1, Generic programming style:

   in the process of learning, I think "pan" here refers to more "extensive" and "general", which has stronger universality. The processing methods of different data types can be solved with the same function instead of writing functions with the same function for different data types, which depends on the template and generic pointer in Chapter 2.
  this chapter is relatively long and is written in two parts: (1) it corresponds to Sections 3.1 to 3.5; and (2) it corresponds to the remaining sections 3.6 to 3.10.

2, Pointer VS generic pointer

2.1 use and limitation of pointer

   the pointer performs very well when processing array.
   for array: we can use a pointer to these containers (point+i) to represent the address of the i-1 element. For example, the following procedures:

int main()
{ 
	int ia[7] = { 1,1,421,8,789,421,1 },*point_array=ia;
	cout << "array:\n" << "Element 3:*(point_array+2):" << *(point_array + 2)
		<< ",Contact on the second and third element addresses:" << point_array + 1
		<< ',' << point_array + 2;
}

   although vector and array are stored continuously on the address (as shown in the figure below)

In C + +, you can use '.' for vector Operator, run the following program:

int main()
{ 
	int ia[7] = { 1,1,421,8,789,421,1 };
	vector<int> vec(ia, ia + 7);
	cout << *vec.begin()<<endl<<*(vec.begin()+4);
}

After running, it is found that 1 and 789 are output, so it is speculated that vec Begin () returns the address of the first element of vec. However, it is difficult to obtain the expected value by pointing to an address in a vector element with a pointer.

As shown in the figure, it seems that after defining a pointer, it cannot point to the address, let alone the arithmetic operation of the pointer.
The limitation of   pointer is that it is very inconvenient to operate containers such as vector, list and deque.

2.2 definition and use of generic pointers


The definition method is as shown in the figure above: change "*" in Section 2.1 to ":: iterator". The following tests whether the generic pointer has the same operation method as the pointer:

It can be seen from the above figure that "+ i" can be used to offset the generic pointer to the i-1 element for the vector container; For the list container, you can't use "+ i" to offset, but you can use "+ +" to offset to the next element.
  summary: in terms of the progress learned so far, generic pointers are pointers to containers. The containers mentioned here refer to vector, list, deque, etc. It is called "generic" because it applies to multiple containers without specifying one; And for different containers, the operation mode is more unified.

2.3. Generic function = template function + generic pointer

   array needs to use pointers, and vector, list and deque use generic pointers. This is too "generic", so it should be more "generic".
Imagine the following scenario: there is an array or a container that needs some processing, such as sorting or adding, deleting, modifying and querying. The data type is unknown, but the function is the same. Take the query element as an example:

template<typename IteratorType, typename elemType> IteratorType
find_elem(IteratorType first, IteratorType last, const elemType& value)
{//first and last are pointers to the same type of data, which may be array,list or vector
	//value may only be one of the data, so the types are different,
	//The find function returns an address that points to a value in the container
	for (; first != last; first++)
		if (*first == value)
			return first;

	cout << "Not elem equivalent" << value;
	return last;
}

This is a function with strong universality. Whether it is an array or a container, this function can be used if the data type is integer, floating point, character or string, and returns the address of the required value. The calling method is as follows

int main()
{
	int array_1[6] = { 15,34,53,72,91,121 };
	vector<int> ivec(array_1, array_1 + 6);
	list<int> ilist(array_1, array_1 + 6);
	//Array*************************************
	int* pia;
	pia = find1(array_1, array_1 + 6, 15);
	cout << *pia<<endl;
	//vector************************************
	vector<int>::iterator p_vec;
	p_vec = find1(ivec.begin(), ivec.end(), 1024);
	if(p_vec!=ivec.end()) cout << *p_vec<<endl;
	else cout << "404 not found\n" ;
	//list**************************************
	list<int>::iterator p_list;
	p_list = find1(ilist.begin(), ilist.end(), 121);
	if (p_list != ilist.end())
		cout << *p_list << endl;
	else cout << "404 not found\n";
}

Generic functions are such functions that are widely used in various containers. C + + comes with more than 60 such functions in total. Functions include searching, sorting, copying, deleting, replacing, etc. Appendix B of the book has examples of use.

3, Common operation of containers

Each container can pass'. ' Operation method call out common operation: the most commonly used is end(),. size(),. empty() and begin(). The other one is used with caution clear(). These operations are very convenient to use.

Use sequential containers

Sequential containers are stored in order. Elements of the same type
1.vector: store elements in a piece of continuous memory. There are four operations for adding, deleting, modifying and querying: when "querying and modifying", because the address is continuous, it can be found by adding a number to the initial address, which is very efficient; "Add, delete" inserts n elements in the middle. All subsequent elements need to be moved back / forward n positions before insertion. The efficiency is not high.
2.list: a two-way linked list that records the addresses of the front and back elements. When "checking and changing", you need to find the corresponding location from the initial address to the next node one by one, which is inefficient. The "add / delete" operation is relatively convenient.
3.deque: queue. Like vector, deleting the first and last elements is more efficient than vector.
  insert operation:
Special insertion

  • Containers push_ Back (value), add a value as the last element
  • Containers push_ Front (value), add a value as the first element

General insertion

  • Insert (address, value), inserts a value at the specified address and returns the address of the inserted value.
  • Insert (address, number, value). Take the specified address as the starting address, insert n identical values, and no return.
  • Insert (address, start address, end address): take the specified address as the start address, insert the value in [start address, end address], and no return.
  • inser (address), add a default value to the address before the specified address. Returns the address of the inserted value.
    In order to get this unknown, the corresponding address is generally obtained in conjunction with the find() function.
      delete:
    Special deletion
  • Containers pop_ Back (value) to delete the last element
  • Containers pop_ Front (value), delete the first element
    Generalized deletion
  • erase (address) to delete the value on the specified address.
  • erase (first address, last address) to delete the elements in the range.

In particular, list cannot perform offset operation. Therefore, if the container is list, the following operations cannot be performed:

 ilist.erase(it1,it1+6);//delete
 //Insert the same principle

Instead, the tail address should be obtained through six '+ +' operations on the generic pointer, and then deleted.

Using generic algorithms

Need #include. Not to mention specifically, it is subcontracting. There are examples in Appendix B.

Topics: C++