Que yo sepa, uno puede asignar elementos a un std::vector de dos maneras:

vec[i] = value

vec.push_back(value)

Sin embargo, el primer método no parece tener efecto en vec.size(), y también se sobrescribe con llamadas posteriores a vec.push_back(). Un ejemplo mínimo para demostrar:

#include <iostream>
#include <vector>

int main()
{
    std::vector<unsigned char> things;
    things.reserve(2);

    things[0] = 'a';
    std::cout << "Size after inserting a: ";
    std::cout << things.size() << std::endl;

    things.push_back('b');
    std::cout << "Size after inserting b: ";
    std::cout << things.size() << std::endl;

    std::cout << "Contents: ";
    for (int i=0; i<2; i++)
    {
        std::cout << things[i] << std::endl;
    }

    return 0;
}

La salida de este programa es:

Size after inserting a: 0
Size after inserting b: 1
Contents: b

Entonces, ¿podría alguien explicarme:

  1. ¿Por qué el tamaño es 0 incluso después de insertar 'a'?

  2. ¿Por qué things.push_back('b') sobrescribe la 'a'?

Nota: Estoy usando unsigned char porque he adaptado este código de un programa que estoy escribiendo que involucra la manipulación de este tipo.

Gracias de antemano.

0
James Roberts 10 may. 2019 a las 14:37

3 respuestas

La mejor respuesta

reserve en realidad no cambia el tamaño del vector. Solo cambia la capacidad del vector, que es diferente de su tamaño real (consulte aquí para obtener una explicación de lo que realmente es). Por lo tanto, su llamada de things[0] = 'a'; ha pasado el tamaño del vector, ya que todavía tiene el tamaño 0 y, por lo tanto, un comportamiento indefinido.

Si llamas a resize en su lugar, obtienes esto:

Size after inserting a: 2
Size after inserting b: 3
Contents: a

Ahora el vector contiene un 'a', un '\0' y un 'b'. '\0' está ahí porque ese es el valor predeterminado de unsigned char, por lo que things.resize(2); deja el vector con dos de ellos antes de cambiar uno a 'a'.

7
Blaze 10 may. 2019 a las 11:43

Una información más

std::vector<unsigned char> things;
things.reserve(2);

Debajo de la asignación, sin verificar los límites del vector, escribirá en la memoria señalada por cosas [0]. Esta operación nunca falla pero causa un comportamiento indefinido debido a la corrupción de la memoria.

things[0]    = 'a';  // 1

Debajo de la asignación, verifique los límites del vector antes de escribir en la memoria señalada por las cosas [0]. Falla si el índice no está dentro del límite del vector y genera la excepción 'std :: out_of_range'.

things.at(0) = 'a'   //2
0
nayab 10 may. 2019 a las 12:48
  1. No lo insertó, lo asignó a un elemento que no existe. Esto tiene un comportamiento indefinido. La asignación no extiende el vector.
  2. Como el vector estaba vacío, push_back agregó el primer elemento.
5
molbdnilo 10 may. 2019 a las 11:44