Не могу объяснить, почему указатели становятся висящими при создании вектора векторов указателей

Рассмотрим следующий код:

#include <iostream>
#include <vector>

using namespace std;

class SomeClass {
public:
SomeClass(int num) : val_(num) {}
int val_;
int val() const { return val_; }
};

// Given a vector of vector of numbers, this class will generate a vector of vector of pointers
// that point to SomeClass.
class Generator {
public:
vector<SomeClass> objects_;
vector<vector<SomeClass*> > Generate(const vector<vector<int> >& input) {
vector<vector<SomeClass*> > out;
for (const auto& vec : input) {
out.push_back({});
for (const int num : vec) {
SomeClass s(num);
objects_.push_back(s);
out.back().push_back(&objects_.back());
}
}
return out;
}
};

int main() {
Generator generator;
auto output = generator.Generate({{2, 3}, {4, 5}, {6}});
for (const auto& vec : output) {
for (const auto* obj : vec) {
printf("%d ",obj->val());
}
printf("\n");
}
return 0;
}

Generate метод в Generator класс просто конвертирует вектор вектора ints к вектору вектора указателей на SomeClass,

SomeClass это просто контейнер для простого int значение с помощью метода получения.

Я ожидал бы следующий вывод:

2 3
4 5
6

Тем не менее, я получаю следующий вывод:

junk_integer junk_integer
4 5
6

Кажется, указатели в первом ряду становятся висящими указателями. Что не так с этим кодом?

0

Решение

Вы храните указатели в vectorЗатем добавляем элементы в вектор. Поскольку вы не резервируете достаточно места для всех добавляемых элементов, когда вектор изменяет размер, он делает недействительными все указатели на старые данные.

Вам нужно либо зарезервировать достаточно места перед сохранением указателей, хранить указатели после того, как вы сохранили все в векторе, который вам нужно сохранить, либо не хранить указатели (возможно, вместо этого сохраните индекс).

1

Другие решения

Все операции, которые увеличивают количество элементов в std::vector, в том числе push_back(), делает недействительными все итераторы (включая указатели), которые ссылаются на элементы вектора, если изменение размера приводит к изменению емкости вектора.

Ваш код делает

objects_.push_back(s);
out.back().push_back(&objects_.back());

в цикле. Каждый звонок objects_.push_back() делает недействительными итераторы objects_и, следовательно, может привести к out.back() содержит недействительные (висячие) указатели.

1

Вы храните указатели на объекты, содержащиеся в generator.objects_, Некоторые из них становятся висящими указателями, когда вы звоните push_back() на что.

Как правило, хранение указателей на объекты в std::vector плохая идея

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector