Деструктор звонит во время интеграции с boost odeint - PullRequest
3 голосов
/ 24 октября 2019

Если я интегрирую систему с бустером odeint, используя класс для определения производной, деструктор этого класса вызывается очень часто.

  1. Предназначено ли это поведение?
  2. Почему это так?
  3. Что мне делать, если я хочу динамически размещать массивы в этом классе?

Например, этот код:

#include <iostream>
#include <boost/numeric/odeint.hpp>

using namespace std;
using namespace boost::numeric::odeint;

class foo
{
public:
    virtual ~foo() {
        std::cout << "destructor called" << std::endl;
    }

    void operator()(const double &x, double &dxdt, double t) const    {
        dxdt = 1;
    }
};

int main( int argc , char **argv )
{
    double x = 0;
    const double dt = 0.1;
    typedef runge_kutta4< double > stepper_type;

    integrate_const( stepper_type() , foo(), x , 0.0 , 10.0 , dt);

    return 0;
}

вызывает деструктор около 400 раз. (Я новичок в C ++)

Ответы [ 2 ]

1 голос
/ 24 октября 2019

Простой: просто отследите вызовы в отладчике до вашего деструктора.

Вы увидите, что первый уровень:

template<class Stepper, class System, class State, class Time> size_t integrate_const( Stepper stepper, System system, State &start_state, Time start_time, Time end_time, Time dt)

, который после несколькихпромежуточные шаги содержат цикл:

while( less_eq_with_sign( static_cast<Time>(time+dt) , end_time , dt ) ) { obs( start_state , time ); st.do_step( system , start_state , time , dt ); ...

, найденный в usr/include/boost/numeric/odeint/integrate/detail/integrate_const.hpp:59

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

Если вы хотите динамически размещать массивы, я бы рекомендовал использовать std::vector, потому что для решения этой проблемы с помощью массивов в стиле C потребуетсямного времени для отладки.

1 голос
/ 24 октября 2019

Деструктор вызывается только один раз в конце программы, если

  1. есть экземпляр foo в основном и
  2. , если std::ref() используется при вызове integrate_const()

Примерно так:

#include <iostream>
#include <boost/numeric/odeint.hpp>
#include <functional>

using namespace boost::numeric::odeint;

class foo
{
public:
    virtual ~foo() {
        std::cout << "destructor called" << std::endl;
    }

    void operator()(const double &x, double &dxdt, double t) const   {
        dxdt = 1;
    }
};

int main( int argc , char **argv )
{
    double x = 0;
    const double dt = 0.1;
    typedef runge_kutta4< double > stepper_type;
    foo myfoo;
    integrate_const( stepper_type() , std::ref( myfoo ), x , 0.0 , 10.0 , dt);
    return 0;
}

Вы можете динамически размещать любые данные в классе foo, например, добавивфункция простого установщика .setData(), которая может быть вызвана из main с помощью

myfoo.setData(myArray);

до вызова integrate_const().

...