Мне нужно создать много экземпляров класса, который, как я считаю, будет делать вектор, как мне нужно. Я читал, что вектор сохраняет только копию, которая не является тем, что я хочу, поскольку мне нужно иметь доступ и вычислять внутри класса. Я попытался сохранить указатель, но он тоже не работает.
Tower.cpp
vector<Projectile*> projectiles;
void Tower::fire(Minion& m)
{
projectiles.push_back(&Projectile(&m, x, 2, y));
}
void Tower::update(Level& level)
{
for (int i = 0; i < projectiles.size(); i++)
{
projectiles.at(i)->update();
}
}
Projectile.cpp
Minion* m;
void Projectile::update()
{
float angle = atan((m->getX() - x) / (m->getY() - z));
x += speed * sin(angle);
z += speed * cos(angle);
}
Хлоп; святые болтающиеся указатели, бэтмен!
projectiles.push_back(&Projectile(&m, x, 2, y));
Кажется, вы пытаетесь сохранить указатели не только локальными переменными, но и временными объектами! Не уверен, что вы ожидаете от этих указателей после завершения этой строки.
Я не вижу, чтобы вы хранили ссылки где-нибудь, хотя (что хорошо).
Вам в основном придется использовать динамическое размещение здесь, чтобы вы могли управлять временем жизни этих объектов самостоятельно, хотя я бы предложил использовать тип интеллектуального указателя, чтобы вам не пришлось брать на себя слишком большую ответственность †:
vector<unique_ptr<Projectile>> projectiles;
// ...
projectiles.emplace_back(new Projectile(&m, x, 2, y));
Пожалуйста, убедитесь, что вы знаете срок службы m
. В общем, я рекомендую внимательно посмотреть на все ваши объекты и выяснить:
прежде чем вы начнете бросать указатели на все. :)
† В частности, избегая необходимости delete
.
Вы не можете этого сделать:
projectiles.push_back(&Projectile(&m, x, 2, y));
То, что вы на самом деле делаете, - это создать переменную типа Projectile, передав ее адрес в векторный объект, а затем экземпляр Projectile
будет уничтожен, поскольку он выходит за рамки. После того, как экземпляр Projectile
вышел из сферы действия, указатель ничего не укажет.
Я подозреваю, что вы пытаетесь это сделать:
projectiles.push_back(new Projectile(&m, x, 2, y));
Помните, однако, что вы все еще несете ответственность за уничтожение тех объектов Projectile
когда вы закончите с ними.
Например, например, происходит утечка памяти:
projectiles.push_back(new Projectile(&m, x, 2, y));
projectiles.erase(0); // <-- Projectile object still exists, you've only deleted the pointer!!!
Это исправит это:
projectiles.push_back(new Projectile(&m, x, 2, y));
// ... later ...
delete projectiles.at(0);
projectiles.erase(0);
Конечно, идеальным способом сделать это было бы использование умного указателя, такого как unique_ptr
или shared_ptr
для управления удалением ваших объектов для вас.
Если вы настаиваете на использовании исходных указателей, но используете Boost, вы также можете использовать класс ptr_vector
для обработки удаления для вас.
Вы храните указатель LOCAL VARIABLES в глобальном std::vector
! Это очень плохо!
Вместо этого я рекомендую использовать контейнер std::shared_ptr
. Например:
std::vector<std::shared_ptr<ProjectFile> > projectfiles;
void Tower::fire(Minion &m)
{
projectfiles.push_back(std::make_shared<ProjectFile>(&m, x, 2, y));
}
Если конструктор ProjectFile не является общедоступным, используйте std::shared_ptr
конструктор вместо std::make_shared
projectfiles.push_back(std::shared_ptr<ProjectFile>(new ProjectFile(&m, x, 2, y)));