与 boost odeint 集成期间的析构函数调用

Destructor calls during integration with boost odeint

如果我集成了一个带有boosts odeint模块的系统,使用一个class来定义导数,这个class的析构函数会经常被调用。

  1. 这种行为是故意的吗?
  2. 为什么会这样?
  3. 这个class想动态分配数组怎么办?

例如,这段代码:

#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++ 的初学者)

如果

,析构函数只在程序结束时调用一次
  1. 在 main 和
  2. 中有一个 foo 的实例化
  3. 如果 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 class 中动态分配任何类型的数据,例如通过添加一个简单的 setter 函数 .setData() 可以从 main 调用

myfoo.setData(myArray);

在调用 integrate_const() 之前。

简单:只需将调试器中的调用追溯到您的析构函数。

你会看到第一层是:

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 风格的数组解决这个问题会花费很多时间来调试。