Under-the-hood STL: объединить std::vector себе без нового вектора

У меня есть вектор STL, который хранит диагонали матрицы. Определенное математическое правило, которое я реализую, говорит мне, что я могу создать новую матрицу диагоналей тензорного произведения, просто беря исходный вектор и конкатенируя копию этого вектора на себя (он удваивается по размеру, а значения повторяются после 1/2 * size()).

Я написал следующий код:

std::vector<int> aVec;

for (int k = 0; k < aVec.size(); k++) aVec.insert(aVec.end(), aVec[k]);

Но я получаю seg-faults, когда я пытаюсь это сделать. Если я создам копию aVec и использую это как значение "insert" вставки, а также использую его для size() в args цикла, он будет работать, но я должен сделать оба этих (иначе я все равно получаю seg-faults).

Может ли кто-нибудь объяснить, что происходит под этим, что делает эту реализацию неработоспособной?

Ответ 1

Скопируйте элементы на неопределенный срок. Обратите внимание, сколько копий спереди:

size_t n = aVec.size();
for (int k = 0; k != n; ++k)
  aVec.push_back(aVec[k]);

В то время как многие алгоритмы С++ лучше выражаются с помощью итераторов begin() и end(), в этом случае ваш доступ через индекс превосходит, так как изменение контейнера может привести к недействительности итераторов, но доступ к элементу останется действительным. Однако вы можете использовать reserve, чтобы избежать этого недействительности:

aVec.reserve(2*aVec.size());
std::copy(aVec.begin(), aVec.end(), std::back_inserter(aVec));

Ответ 2

Использовать операции на основе итератора:

vec.reserve(vec.size() * 2);
vec.insert(vec.end(), vec.begin(), vec.end());

Ответ 3

Вы должны прочитать значение aVec.size() один раз, прежде чем начинать добавлять элементы в aVec.