Как обрабатывать вектор атрибута вектора?

В классе C ++ под названием ClassA у меня ранее был атрибут типа массив с двойным измерением другого класса с именем ClassB:

частный: матрица ClassB [ROWS] [COLS];

где ROWS и COLS, где статические значения.

Сейчас я модифицирую приложение, чтобы иметь возможность указывать два измерения в командной строке. Я подумываю использовать вместо этого vector<vector<ClassB>>. Прежде чем перейти к этому решению, мне интересно, как такой объект будет инициализирован по умолчанию. vector атрибуты назначаются автоматически, но что будет с вложенными векторами? Стоит ли мне их распределять самому?

ПРИМЕЧАНИЕ. Мне не удалось найти ответ на этот вопрос, поэтому сообщите мне, если это дубликат.


person Manuel Selva    schedule 05.10.2015    source источник
comment
Обратите внимание, что лучшим решением может быть запись класса 2D-матрицы с использованием одного вектора для хранения.   -  person juanchopanza    schedule 06.10.2015


Ответы (1)


Конструктор по умолчанию std::vector<std::vector> будет строить вектор векторов, но для его элементов (в данном случае внутренних векторов) не будет выделена никакая память, если вы явно не укажете это. Если вам нужно выделить память, соответствующую ROWS x COLS, используйте, например,

std::vector<std::vector<int>> vec(ROWS, std::vector<int>(COLS));

Если вы просто скажете

std::vector<std::vector<int>> vec(ROWS);

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

Конструкторы std::vector во всей красе определены здесь.

Но в целом использование вложенных векторов - плохая идея, поскольку вы теряете локальность данных, и код может работать медленнее. Другими словами, нет гарантии, что данные будут непрерывными в памяти. vector<vector> хранит данные внутри как массив указателей, и хотя указатели хранятся непрерывно, не гарантируется, что каждый фрагмент данных, на который они указывают, будет смежным в памяти. Лучше использовать «сплющенный» вектор и переводить из 2D в 1D и наоборот.

person vsoftco    schedule 05.10.2015
comment
Помните, что если T является чем-то более сложным, чем int, то будет вызван конструктор Ts. - person Zereges; 05.10.2015
comment
@Zereges Да, вызывается конструктор элемента по умолчанию. - person vsoftco; 05.10.2015
comment
Спасибо за очень быстрый ответ. я должен сделать выделение, которое вы упомянули внутри конструктора моего ClassA? Будет ли вызываться конструктор T, даже если размер вложенных векторов равен 0, как в этом примере? - person Manuel Selva; 05.10.2015
comment
Arf, 0 - это начальное значение, а не размер! я устал - person Manuel Selva; 05.10.2015
comment
@ManuelSelva Если вы точно знаете, что все внешние векторы имеют размер COLS, тогда да, вы можете сделать что-то вроде: struct ClassA { std::vector<std::vector<int>> vec; ClassA(): vec(ROWS, std::vector<int>(COLS)){} }; А также, если начальное значение равно 0, вам не нужно явно указывать его. Конструктор типа по умолчанию инициализирует его значением 0. - person vsoftco; 06.10.2015
comment
@vsoftco Еще раз спасибо. Теперь я вижу, что класс, который я хочу поместить в свой вектор вектора, является абстрактным :) - person Manuel Selva; 06.10.2015
comment
@ManuelSelva Тогда у вас проблема :) - person vsoftco; 06.10.2015
comment
Позвольте нам продолжить это обсуждение в чате. - person Manuel Selva; 06.10.2015