Un pequeño estudio de redimensionamiento y reserva de vectores.

Descripción del problema

Encontré un problema hoy. Un colega usa la reserva de vector y toma directamente la primera aridad. El pseudocódigo es el siguiente:

m_arrsAP.reserve(uCount);
AP* pAP = &m_arrsAP[0];

El resultado se informa de la siguiente manera:

vector subscript out of range

En ese momento, se pensó en la diferencia entre el tamaño y la capacidad, por lo que cambiar el código para cambiar el tamaño realmente estuvo bien. Sin embargo, también han surgido los siguientes problemas: Las
preguntas son las siguientes:

  1. ¿Por qué no hay ningún error en la versión, sino un error en la depuración?
  2. ¿Cuál es el significado de la diferencia entre tamaño y capacidad?
  3. ¿Cuál es la diferencia entre redimensionar y reservar?
  4. Reserve cambiará el tamaño del espacio, luego cambiará la dirección, debe verificarlo.

La diferencia entre lanzamiento y depuración

Es fácil saberlo mirando el código. Solo está disponible cuando el Nivel bajo Depuración es 2, y puede no informar un error si se establece el nivel de vs.

    reference operator[](size_type _Pos)
        {    // subscript mutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
        if (size() <= _Pos)
            {    // report error
            _DEBUG_ERROR("vector subscript out of range");
            _SCL_SECURE_OUT_OF_RANGE;
            }

 #elif _ITERATOR_DEBUG_LEVEL == 1
        _SCL_SECURE_VALIDATE_RANGE(_Pos < size());
 #endif /* _ITERATOR_DEBUG_LEVEL */

        return (*(this->_Myfirst() + _Pos));
        }

tamaño 和 capacidad

En general, todos conocen estas dos diferencias, el tamaño es el número de elementos en el vector actual, la capacidad es el número de elementos en el vector actual y el tamaño <= capacidad

redimensionar 和 reservar

Después de comprender la diferencia entre tamaño y capacidad, cambiar el tamaño y reservar, naturalmente, cambiar las operaciones relacionadas con estos dos valores. Pero la realización de estas dos funciones en última instancia tiene muchas cosas que mirar, mirar hacia abajo:

redimensionar

Código fuente:

    void resize(size_type _Newsize)
        {    // determine new length, padding as needed
        if (_Newsize < size())
            _Pop_back_n(size() - _Newsize);
        else if (size() < _Newsize)
            {    // pad as needed
            _Reserve(_Newsize - size());
            _TRY_BEGIN
            _Uninitialized_default_fill_n(this->_Mylast(), _Newsize - size(),
                this->_Getal());
            _CATCH_ALL
            _Tidy();
            _RERAISE;
            _CATCH_END
            this->_Mylast() += _Newsize - size();
            }
        }

Descripción:

  • Si _Newsize es más pequeño que el tamaño actual, extraiga los elementos adicionales
  • Si _Newsize es mayor que el tamaño actual, _Reserve es responsable de crear espacio insuficiente, esta vez la memoria cambiará
  • La función _Uninitialized_default_fill_n es responsable de llenar el espacio recién agregado con el primer arity

_Reserva

    void _Reserve(size_type _Count)
        {    // ensure room for _Count new elements, grow exponentially
        if (_Unused_capacity() < _Count)
            {    // need more room, try to get it
            if (max_size() - size() < _Count)
                _Xlen();
            _Reallocate(_Grow_to(size() + _Count));
            }
        }

Descripción:

  • max_size era 1073741823 cuando lo imprimí yo mismo, así que lo comprobé aquí
  • La función _Grow_to intenta aumentar la capacidad en un 50%. Si _Count es mayor que la capacidad + capacidad / 2, use _Count directamente
  • _Reasignar reasigna el espacio, la dirección cambiará

reserva

    void reserve(size_type _Count)
        {    // determine new minimum length of allocated storage
        if (capacity() < _Count)
            {    // something to do, check and reallocate
            if (max_size() < _Count)
                _Xlen();
            _Reallocate(_Count);
            }
        }

Es casi el mismo código que _Reserve ~

Pregunta respuesta

Código de prueba:

void VECTOR_TEST::TestSizeAndCapacity()
{
    PrintSizeAndCapacity();

    m_vecTest.reserve(10);
    PrintSizeAndCapacity();

    m_vecTest.resize(5);
    PrintSizeAndCapacity();

    m_vecTest.resize(10);
    PrintSizeAndCapacity();

    m_vecTest.push_back(1);
    PrintSizeAndCapacity();

    m_vecTest.resize(5);
    PrintSizeAndCapacity();

    m_vecTest.reserve(5);
    PrintSizeAndCapacity();
}

El resultado:

max size: 1073741823 vector size: 0 vector capacity: 0
max size: 1073741823 vector size: 0 vector capacity: 10
max size: 1073741823 vector size: 5 vector capacity: 10
address: 035104F8
max size: 1073741823 vector size: 10 vector capacity: 10
address: 035104F8
max size: 1073741823 vector size: 11 vector capacity: 15
address: 0351A050
max size: 1073741823 vector size: 5 vector capacity: 15
address: 0351A050
max size: 1073741823 vector size: 5 vector capacity: 15
address: 0351A050

1. ¿Por qué no hay ningún error en la versión, sino un error en la depuración?

Ver código fuente

2. ¿Cuál es el significado de la diferencia entre tamaño y capacidad?

Es el significado que entendemos, el tamaño es para satisfacer las necesidades dinámicas

3. ¿Cuál es la diferencia entre redimensionar y reservar?

De hecho, reservar y cambiar el tamaño hacen lo mismo al asignar memoria, pero reservar casi siempre asigna memoria, que transfiere datos y consume más energía. Por lo tanto, use el cambio de tamaño tanto como sea posible. Esta es la mayor diferencia entre los dos.

4. reserve cambiará el tamaño del espacio, luego cambiará la dirección, debe verificar

Sí, mira la salida

Publicó 41 artículos originales · elogió 7 · 20,000+ visitas

Supongo que te gusta

Origin blog.csdn.net/pkxpp/article/details/85317246
Recomendado
Clasificación