Mecanismo de implementação subjacente do vetor C ++ (vetor STL) (fácil de entender)

Entre os muitos contêineres da STL, o vetor é um dos contêineres mais comumente usados.A estrutura de dados subjacente é muito simples, apenas um espaço de memória linear contínuo.
Ao analisar o código-fonte do contêiner de vetor, não é difícil descobrir que ele é representado por 3 iteradores (que podem ser entendidos como ponteiros):

//_Alloc 表示内存分配器,此参数几乎不需要我们关心
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
    
    
    ...
protected:
    pointer _Myfirst;
    pointer _Mylast;
    pointer _Myend;
};

Entre eles, _Myprimeiro aponta para a posição inicial do byte do objeto contêiner vetorial; _Mylast aponta para o byte final do último elemento atual; _myend aponta para o byte final do espaço de memória ocupado por todo o contêiner vetorial.

A Figura 1 demonstra para onde os três iteradores acima apontam.
Insira a descrição da imagem aqui
Conforme mostrado na Figura 1, por meio desses 3 iteradores, um contêiner vetorial com 2 elementos e capacidade de 5 pode ser representado.
Com base nisso, combinar os três iteradores em pares também pode expressar diferentes significados, por exemplo:

  • _Myfirst e _Mylast podem ser usados ​​para representar o espaço de memória atualmente usado no contêiner de vetor;
  • _Mylast e _Myend podem ser usados ​​para representar o espaço de memória livre do contêiner de vetor;
  • _Myfirst e _Myend podem ser usados ​​para representar a capacidade do contêiner de vetor.
    Para um contêiner de vetor vazio, uma vez que não há alocação de espaço para nenhum elemento, _Myfirst, _Mylast e _Myend são todos nulos.
    Usando de forma flexível esses três iteradores, o contêiner de vetor pode facilmente implementar quase todas as funções, como a primeira e a última identificação, tamanho, contêiner e julgamento de contêiner vazio, como:
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
    
    
public:
    iterator begin() {
    
    return _Myfirst;}
    iterator end() {
    
    return _Mylast;}
    size_type size() const {
    
    return size_type(end() - begin());}
    size_type capacity() const {
    
    return size_type(_Myend - begin());}
    bool empty() const {
    
    return begin() == end();}
    reference operator[] (size_type n) {
    
    return *(begin() + n);}
    reference front() {
    
     return *begin();}
    reference back() {
    
    return *(end()-1);}
    ...
};

A essência da expansão vetorial

Além disso, é preciso destacar que quando o tamanho e a capacidade do vetor são iguais (tamanho == capacidade), ou seja, quando ele está cheio, se você adicionar elementos a ele, o vetor precisa ser expandido. O processo de expansão do recipiente vetorial requer as seguintes 3 etapas:

  1. Abandone completamente o espaço de memória existente e solicite um espaço de memória maior;
  2. Mova os dados do antigo espaço de memória para o novo espaço de memória na ordem original;
  3. Finalmente, o antigo espaço de memória é liberado.
    Isso também explica porque os ponteiros, referências e iteradores relacionados ao contêiner de vetor podem se tornar inválidos após a expansão.

Pode-se ver que a expansão do vetor consome muito tempo . Para reduzir o custo de realocação de espaço de memória, o vetor irá solicitar mais espaço de memória do que o usuário precisa cada vez que ele se expandir (esta é a origem da capacidade do vetor, ou seja, capacidade> = tamanho) para uso posterior.
Quando o contêiner de vetor é expandido, diferentes compiladores solicitam mais espaço de memória de forma diferente. Tome o VS como exemplo, ele irá expandir 50% da capacidade do contêiner existente.

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    
    
    vector<int> a;
    cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;
    for (int i = 0; i < 10; i++)
    {
    
    
        a.push_back(i);
        cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;
    }
    return 0;
}

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/J_avaSmallWhite/article/details/109232653
Recomendado
Clasificación