Вектор инициализации вектора

мне трудно получить мою голову, обернутую вокруг того, как инициализировать вектор векторов.

typedef вектор > > > DataContainer;

Я хочу, чтобы соответствовать

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

обращение к элементам не является проблемой. Это должно быть так же просто, как что-то вроде

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

проблема в том, что мне нужно заполнить его данными, выходящими из строя из файла, так что последовательные элементы должны разместите что-то вроде

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

поэтому мне нужно инициализировать V из V заранее.

я психую себя или это так просто, как

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

не похоже, что это должно сработать. Каким-то образом сначала должны быть инициализированы векторы верхнего уровня.

любая помощь ценится. Я уверен, что это проще, чем я себе представляю.

3 ответов


  • пожалуйста не используйте вложенные векторы если размер вашего хранилища известен заранее, т. е. конкретная причина почему, например, первый индекс должен иметь размер 6 и никогда не изменится. Просто используйте простой массив. Еще лучше, используйте boost::array. Таким образом, вы получаете все преимущества наличия простого массива (экономите огромное количество пространства, когда вы идете многомерным) и преимущества наличия реального объекта экземпляр.

  • пожалуйста не используйте вложенные векторы если ваше хранилище должно быть прямоугольные, т. е. вы можете изменить размер одного или нескольких измерений, но каждая "строка" должна быть одинаковой длины в какой-то момент. Использовать boost::multi_array. Таким образом, вы документируете "это хранилище прямоугольное", экономите огромное пространство и все равно получаете возможность изменять размер, преимущества наличия реального объекта и т. д.

насчет std::vector заключается в том, что он (a) предназначен для изменения размера и (b) не заботится о его содержимом ни в малейшей степени, если они имеют правильный тип. Это означает, что если у вас есть vector<vector<int> >, тогда все "векторы строк" должны поддерживать свою собственную отдельную бухгалтерскую информацию о том, как долго они есть, даже если вы хотите обеспечить, чтобы они были одинаковой длины. Это также означает, что все они управляют отдельными выделениями памяти, что снижает производительность (поведение кэша) и тратит еще больше места из-за как!--4--> перераспределяет. boost::multi_array разработан с ожиданием, что вы можете изменить его размер, но не будете постоянно изменять его, добавляя элементы (строки, для 2-мерного массива / граней, для 3-мерного массива / и т. д.) до конца. std::vector предназначен для (потенциально) отходов пространства, чтобы убедиться, что операция не медленная. boost::multi_array предназначен для экономии места и держать все аккуратно организованы в памяти.

, который сказал:

Да, вы делаете нужно что-то сделать, прежде чем вы сможете индексировать в вектор. std::vector не будет волшебным образом вызывать появление индексов, потому что вы хотите сохранить что-то там. Тем не менее, с этим легко справиться:

вы можете по умолчанию-инициализировать вектор с соответствующим количеством нулей, а затем заменить их, используя (size_t n, const T& value = T()) конструктор. То есть,

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

потому что" построенный по умолчанию " int имеет значение 0.

в вашем случае, нам нужно чтобы указать размер каждого измерения, создайте под-векторы соответствующего размера и позвольте конструктору скопировать их. Это выглядит так:

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))));

то есть безымянный d1 построен размер 31, который используется для инициализации по умолчанию d2, который используется для инициализации по умолчанию d3, который используется для инициализации result.

есть и другие подходы, но они намного неуклюже, если вы просто хотите, чтобы началась куча нулей. Если вы собираетесь прочитать весь набор данных из файла, но:

  • можно использовать .push_back() для добавления к вектору. Сделайте пустой d1 как раз перед внутренней петлей, в которой вы неоднократно .push_back() чтобы заполнить его. Сразу после петли, вы .push_back() результат на d2, который вы создали только перед внутренним циклом, и так далее.

  • вы можете заранее изменить размер вектора с помощью .resize(), а затем индексировать в него обычно (до размера, который вы изменили).


EDIT: я признаю, что этот код не элегантен. Мне нравится @Karl answer, который является правильным путем.

этот код компилируется и тестируется. Он напечатал 208320 нулей, которые ожидаются (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;
}

вам, вероятно, придется установить размер или зарезервировать память

Не могли бы вы сделать for-each или вложенный для этого вызов

myVector.resize(x); //or size

на каждом уровне.