Прежде всего, вы получите почти мгновенный переполнение стека с помощью этого кода.
Ваша основная codepath выглядит следующим образом, в псевдокоде:
func() {
path = RAND(1, 3);
if(path == 1) /*DO STUFF*/ func();
else if(path == 2) /*DO STUFF*/ func();
else /*DO STUFF*/ func();
}
Таким образом, независимо от этих шагов, являются ли «одновременное» или нет, ваш код никогда не заканчивается в любом случае. Если вы хотите, чтобы код в конечном итоге остановился, вы должны иметь случайное число в диапазоне, который не только выводит числа [1, 3]
.
int RandomNumber= qrand() %4; //Will stop when RandomNumber == 0
Если есть более явное условие, когда рекурсия следует прекратить (например, когда energy == 0
), вам нужно закодировать, что вместо этого.
Ваша вторая проблема заключается в том, что не ясно, что вы подразумеваете, выполняя все эти шаги «одновременно». Ожидаете ли вы, что все пути будут выполняться параллельно в нескольких потоках?
Вам нужно написать что-то вроде этого:
std::thread t1([=]{
LightParticle* i=new LightParticle(energy, position);
int speed = 3;
i->SimulatePath(time, speed, i->GetPosition());
i->GetPosition().Print();
energy--;
if(condition_to_continue_recursing()) {
Simulate(energy, i->GetPosition());
}
});
std::thread t2([=]{
MediumParticle* j=new MediumParticle(energy, position);
MediumParticle* k=new MediumParticle(energy, position);
int speed = 2;
j->SimulatePath(time,speed, position);
k->SimulatePath(time,speed, position);
j->GetPosition().Print();
k->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, j->GetPosition());
Simulate(energy, k->GetPosition());
}
});
std::thread t3([=]{
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
int speed = 1;
l->SimulatePath(time,speed, position);
l->GetPosition().Print();
m->SimulatePath(time,speed, position);
m->GetPosition().Print();
n->SimulatePath(time,speed, position);
n->GetPosition().Print();
if(condition_to_continue_recursing()) {
Simulate(energy, l->GetPosition());
Simulate(energy, m->GetPosition());
Simulate(energy, n->GetPosition());
}
});
t1.join();
t2.join();
t3.join();
Но независимо от того condition_to_continue_recursing()
это придется решать вам; Я не знаю достаточно о вашей общей задаче, чтобы ответить на это. Кроме того, это порождает абсурдное количество потоков, если ваш condition_to_continue_recursing
весьма значителен; использование пула потоков может быть предпочтительным. И все это зависит от того, решите ли вы, что использование потоков идеально подходит для такого рода задач, что для меня не очевидно (для меня).
Ваша третья проблема заключается в том, что этот фрагмент кода усеян довольно значительными ошибками дизайна.
HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);
Каждый из этих указателей будет течь. Так как объекты используются только в пределах, в которых они были определены, использование std::unique_ptr
, вероятно, идеально:
std::unique_ptr<HeavyParticle> l = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> m = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> n = std::make_unique<HeavyParticle>(energy, position);
EDIT: С другой стороны, нет никакой реальной хорошей причины, почему вы должны использовать указатели в этом контекста в первую очередь. Следующий код будет работать прекрасно без каких-либо утечек памяти или изменения функциональности вашего кода:
HeavyParticle l(energy, position);
HeavyParticle m(energy, position);
HeavyParticle n(energy, position);
int speed = 1;
l.SimulatePath(time,speed, position);
l.GetPosition().Print();
m.SimulatePath(time,speed, position);
m.GetPosition().Print();
n.SimulatePath(time,speed, position);
n.GetPosition().Print();
Simulate(energy, l.GetPosition());
Simulate(energy, m.GetPosition());
Simulate(energy, n.GetPosition());
Вы также, вероятно, не следует использовать qrand
.
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position)
{
std::uniform_int_distribution<int> distribution(0, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
Лучшая конструкция передаст двигатель в функцию.
Альтернатива:
std::default_random_engine engine(std::random_device()());
void Reaction::Simulate(double energy, TwoVector position)
{
if(energy <= 0) return;
std::uniform_int_distribution<int> distribution(1, 3);
int RandomNumber = distribution(engine);
/*... Whatever*/
Там намного больше к этому, но есть много, чтобы копаться в. Надеюсь, это даст хорошую отправную точку.
Для будущих вопросов, пожалуйста, убедитесь, что ваш код правильно отформатирован. Некорректно отформатированный код чрезвычайно трудно анализировать и, следовательно, крайне сложно отлаживать. – Xirema
wow, который выглядит так аккуратно, спасибо –
Возможно, было бы лучше представить все частицы в структуре, такие как 'std :: vector', а затем запустить' Simulate' на все то для одной итерации и повторить столько раз как вы считаете нужным. Избегайте «новых». С помощью вектора вы просто используете 'push_back' для добавления каждой новой частицы. – wally