Pregunta

Estoy teniendo un tiempo difícil conseguir mi cabeza envuelta en torno a la forma de inicializar un vector de vectores.

typedef vector >>> DataContainer;

Quiero que esto se ajusta a

level_1 (2 elements/vectors)
   level_2 (7 elements/vectors)
      level_3 (480 elements/vectors)
         level_4 (31 elements of float)

Dirigiéndose a los elementos no es la cuestión. Eso debería ser tan simple como algo parecido a

dc[0][1][2][3];

El problema es que necesito a llenarlo con los datos procedentes de fuera de servicio desde un archivo de tal manera que los elementos sucesivos deben ser colocados algo así como

dc[0][3][230][22];
dc[1][3][110][6]; //...etc

Así se tiene que inicializar la V de V de antemano.

I Am psyching a mí mismo o esto es tan simple como

for 0..1
    for 0..6
        for 0..479
           for 0..30
               dc[i][j][k][l] = 0.0;

No parece que debería funcionar. De algún modo los vectores de nivel superior deben inicializarse primero.

Cualquier ayuda apreciada. Estoy seguro de que esto sea más simple que estoy imaginando.

¿Fue útil?

Solución

  • no utilice anidada vectores si el tamaño de su almacenamiento se sabe de antemano , es decir, no es un razón específica ¿Por ejemplo, el primer índice debe ser de tamaño 6, y nunca va a cambiar. Sólo tiene que utilizar un array plano. Mejor aún, el uso boost::array. De esta manera, se obtiene todos los beneficios de tener un array plano (ahorrar enormes cantidades de espacio cuando se va multidimensional), y los beneficios de tener un verdadero instancias de objetos.

  • no utilice anidada vectores si su almacenamiento debe ser rectangular , es decir, es posible cambiar el tamaño de una o más de las dimensiones, pero cada necesidad "fila" tener la misma longitud en algún momento. Uso boost::multi_array. De esta manera, se documentan "este almacenamiento es rectangular", guardar grandes cantidades de espacio y aún así obtener la capacidad de cambiar el tamaño, beneficios de tener un objeto real, etc.

Lo que pasa std::vector es que (a) está destinado a ser de tamaño variable y (b) no se preocupa por su contenido en la menor, siempre y cuando sean del tipo correcto. Esto significa que si usted tiene un vector<vector<int> >, entonces todos los "vectores fila" deben mantener su propia información de la contabilidad separada acerca de cuánto tiempo que son - incluso si desea exigir que todos son de la misma longitud. También significa que todos ellos manejan las asignaciones de memoria por separado, lo que perjudica el rendimiento (comportamiento de la caché) y desechos aún más espacio debido a la forma en reasigna std::vector. boost::multi_array está diseñado con la expectativa de que es posible que desee cambiar su tamaño, pero no será constantemente cambiar su tamaño añadiendo elementos (filas, para un 2-dimensional array / caras, para una matriz de 3 dimensiones / etc) hasta el final . std::vector está diseñado para (potencialmente) un desperdicio de espacio para asegurarse de que la operación no es lento. boost::multi_array está diseñado para ahorrar espacio y mantener todo muy bien organizado en la memoria.

Dicho

Sí, sí es necesario hacer algo antes de que pueda índice en el vector. std::vector no causar mágicamente los índices de pop en existencia debido a que desea almacenar algo allí. Sin embargo, esto es fácil de tratar:

Puede default-inicializar el vector con la cantidad apropiada de ceros en primer lugar, y luego reemplazarlos, utilizando el constructor (size_t n, const T& value = T()). Es decir,

std::vector<int> foo(10); // makes a vector of 10 ints, each of which is 0

porque un "default-construido" int tiene el valor 0.

En su caso, tenemos que especificar el tamaño de cada dimensión, mediante la creación de sub-vectores que son del tamaño adecuado y dejar que el constructor copiarlos. Esto se parece a:

typedef vector<float> d1;
typedef vector<d1> d2;
typedef vector<d2> d3;
typedef vector<d3> d4;
d4 result(2, d3(7, d2(480, d1(31))));

Es decir, un d1 sin nombre se construye de tamaño 31, que se utiliza para inicializar el d2 predeterminado, que se utiliza para inicializar el d3 predeterminado, que se utiliza para inicializar result.

Hay otros enfoques, pero son mucho más torpe si lo que desea es un montón de ceros para empezar. Si usted va a leer todo el conjunto de datos de un archivo, sin embargo:

  • Se puede utilizar .push_back() para anexar a un vector. Hacer una d1 vacío justo antes del bucle más interno, en el que .push_back() varias veces para llenarlo. Justo después del bucle, .push_back() el resultado en el d2 la que se creó antes de la próxima bucle más interno, y así sucesivamente.

  • Puede cambiar el tamaño de un vector de antemano con .resize(), y luego índice en lo que normalmente (hasta la cantidad que ha cambiado de tamaño a).

Otros consejos

Probablemente tendría que establecer un tamaño o reserva de memoria

Podría hacer una for-each anidado o para que llame

myVector.resize(x); //or size

en cada nivel.

EDIT: Tengo que admitir que este código no es elegante. Yo como respuesta @Karl que es el camino correcto a seguir.

Este código se compila y se prueba. Se impreso 208320 ceros que se espera (2 * 7 * 480 * 31)

#include <iostream>
#include <vector>

using namespace std;

typedef vector< vector < vector < vector< float > > > > DataContainer;

int main()
{
    const int LEVEL1_SIZE = 2;
    const int LEVEL2_SIZE = 7;
    const int LEVEL3_SIZE = 480;
    const int LEVEL4_SIZE = 31;

    DataContainer dc;

    dc.resize(LEVEL1_SIZE);
    for (int i = 0; i < LEVEL1_SIZE; ++i) {
        dc[i].resize(LEVEL2_SIZE);
        for (int j = 0; j < LEVEL2_SIZE; ++j) {
            dc[i][j].resize(LEVEL3_SIZE);
            for (int k = 0; k < LEVEL3_SIZE; ++k) {
                dc[i][j][k].resize(LEVEL4_SIZE);
            }
        }
    }

    for (int i = 0; i < LEVEL1_SIZE; ++i) {
        for (int j = 0; j < LEVEL2_SIZE; ++j) {
            for (int k = 0; k < LEVEL3_SIZE; ++k) {
                for (int l = 0; l < LEVEL4_SIZE; ++l) {
                    dc[i][j][k][l] = 0.0;
                }
            }
        }
    }

    for (int i = 0; i < LEVEL1_SIZE; ++i) {
        for (int j = 0; j < LEVEL2_SIZE; ++j) {
            for (int k = 0; k < LEVEL3_SIZE; ++k) {
                for (int l = 0; l < LEVEL4_SIZE; ++l) {
                    cout << dc[i][j][k][l] << " ";
                }
            }
        }
    }

    cout << endl;
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top