What exactly is a "container adapter"?

First, we need to understand what the adapter does? In fact, it is an interface conversion device, which requires us to use specific methods to operate things that we could not otherwise operate. To give an example, for example, one of your devices supports a serial cable, and your computer supports a USB port. At this time, we don’t need to buy a USB-supporting device. We only need a gadget that converts a serial port to the USB port. Your device can be connected to the usb socket, and it is the adapter.

What does the container adapter really mean?

In different scenarios, because different sequential containers use different data structures at the bottom, the execution efficiency of the container adapter is also different. But usually, just use the default base container. Of course, we can also modify it manually. For the specific method of modifying the base container of the container adapter, please see the following custom Stack class demonstration:

Take Stack as an example. The container adapter means that the bottom layer uses different containers. Take the vector array used by Stack as an example:

Person.h

#pragma once  
  
#include <iostream>  
#include <sstream>  
#include <string>  
using namespace std;  
  
class Person  
{  
private:  
    string name;  
    int age;  
public:  
    Person() = default;  
    Person(int age, string name);  
    Person(const Person& obj);  
    Person(Person&& obj);  
  
    Person& operator = (Person obj);  
    friend ostream& operator << (ostream& cout, Person& obj);  
  
    ~Person() = default;  
};  

 

Person.cpp

#include "Person.h"  
  
Person::Person(int age, string name)  
{  
    this->age = age;  
    this->name = name;  
}  
  
Person::Person(const Person & obj)  
{  
    this->age = obj.age;  
    this->name = obj.name;  
}  
  
Person::Person(Person && obj)   
{  
    this->name = obj.name;  
    this->age = obj.age;  
}  
  
Person & Person::operator=(Person obj)  
{  
    this->age = obj.age;  
    this->name = obj.name;  
    return *this;  
}  
  
ostream & operator<<(ostream & cout, Person & obj)  
{  
    cout << obj.name << "的年龄为" << obj.age;  
    return cout;  
}  

Here we must pay attention: the form of the copy constructor: the copy constructor member function must be defined as a const attribute

Main.cpp

#include "Stack.hpp"  
#include "Person.h"  
#include <iostream>  
#include <string>  
using namespace std;  
  
int main()  
{  
    Person Person_Obj1(19, "张三");  
    Stack<Person> Stack_Obj1;  
    Stack_Obj1.Push(Person_Obj1);  
    Stack_Obj1.ShowInf();  
}  

 

Stack.hpp

#include <iostream>  
using namespace std;  
#include <vector>  
#include <exception>  
#include <algorithm>  
  
template <class T>  
class Stack  
{  
private:  
    vector<T> element;  
public:  
    Stack() = default;  
    Stack(T obj);  
    Stack(vector<T> element);  
    Stack(Stack& obj);  
  
    void Push(T obj);  
    void Pop();  
    T Top();  
    void ShowInf();  
  
    ~Stack() = default;  
};  
  
template<class T>  
inline Stack<T>::Stack(T obj)  
{  
    this->element.push_back(obj);  
}  
  
template<class T>  
inline Stack<T>::Stack(vector<T> element)  
{  
    this->element = element;  
}  
  
template<class T>  
inline Stack<T>::Stack(Stack& obj)  
{  
    this->element = obj.element;  
}  
  
template<class T>  
inline void Stack<T>::Push(T obj)  
{  
    this->element.push_back(obj);  
}  
  
template<class T>  
inline void Stack<T>::Pop()  
{  
    if (this->element.empty())  
    {  
        throw out_of_range("empty stack");  
    }  
    this->element.pop_back();  
}  
  
template<class T>  
inline T Stack<T>::Top()  
{  
    if (this->element.empty())  
    {  
        throw out_of_range("empty stack");  
    }  
    return *(this->element.begin());  
}  
  
template<class T>  
inline void Stack<T>::ShowInf()  
{  
    if (this->element.empty())  
    {  
        throw out_of_range("empty stack");  
    }  
    for_each(this->element.begin(), this->element.end(), [](T& obj) {cout << obj << " "; });  
    cout << endl;  
}  

 

We see that we can use vector as the bottom container of the Stack stack to perform various operations. This is based on the Stack properties, such as: I want to frequently push and pop the stack. We can choose the vector container. The essence of Stack pops The above is to delete and insert elements at the end of the vector array.

But the queue is different. The queue is first-in, first-out, that is, inserting elements before the first element of the array, and deleting elements at the end of the array. This operation is obviously the most suitable for deque containers.

We select different underlying containers to improve program performance, which is the role of container adapters.

Guess you like

Origin blog.csdn.net/weixin_45590473/article/details/112212090