Вектор инициализации вектора
мне трудно получить мою голову, обернутую вокруг того, как инициализировать вектор векторов.
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
на каждом уровне.