Я хотел бы создать собственный векторный класс Eigen, в котором были бы именованные ссылки на определенные c сегменты (или блоки для матриц). Это должно позволить мне сразу изменять определенные c части вектора без необходимости запоминать указанные c индексы, что, на мой взгляд, приводит к более удобочитаемому коду при работе с большими векторами / матрицами. Следуя некоторым советам в документации Eigen, я придумал следующую демонстрационную реализацию:
#include "Eigen/Core"
#include <iostream>
struct State : public Eigen::Matrix<double,12,1>{
static constexpr unsigned int SIZE = 12;
using data_t = Eigen::Matrix<double,SIZE,1>;
Eigen::Ref<Eigen::Vector3d> pos;// Same problem using Eigen::VectorBlock<data_t,3>
Eigen::Ref<Eigen::Vector3d> ang;
Eigen::Ref<Eigen::Vector3d> vel;
Eigen::Ref<Eigen::Vector3d> ang_vel;
State(const Eigen::Vector3d& pos, const Eigen::Vector3d& ang, const Eigen::Vector3d& vel, const Eigen::Vector3d& ang_vel)
: State(){
this->pos = pos;
this->ang = ang;
this->vel = vel;
this->ang_vel = ang_vel;
}
State() : State(data_t::Zero()){}
// This constructor allows you to construct State from Eigen expressions
template<typename OtherDerived>
State(const Eigen::MatrixBase<OtherDerived>& other)
: data_t(other), pos(this->segment<3>(0)), ang(this->segment<3>(3)), vel(this->segment<3>(6)), ang_vel(this->segment<3>(9)){}
// This method allows you to assign Eigen expressions to State
template<typename OtherDerived>
State& operator=(const Eigen::MatrixBase<OtherDerived>& other)
{
this->data_t::operator=(other);
return *this;
}
};
State createState(){
State x;
x.pos = Eigen::Vector3d(1.0,1.0,1.0);
return x;
}
int main(){
State x = createState();
std::cout << x.pos << std::endl;
State dx;
dx.pos = x.pos/2;
std::cout << dx.pos << std::endl;
return 0;
}
Этот код отлично работает в режиме Release (с включенной оптимизацией) и печатает
1, 1, 1 0,5, 0,5, 0,5
Однако, когда я включаю режим отладки (без оптимизаций и добавленных символов отладки), он печатает что-то вроде
-9.25596e + 61, -9.25596 е + 61, 0 -4.62798e + 61, -4.62798e + 61, -4.62798e + 61
Я использую MSV C Build tools 2019 на ноутбуке windows 10 для компиляции и запуска этого примера. При более внимательном изучении с помощью отладчика кажется, что данные в самом векторе все еще не повреждены, однако названные ссылки теперь указывают на разные места в памяти (висячие указатели). Также важно отметить, что такое поведение наблюдается только для State
, возвращаемого другой функцией. Если State
построен внутри основной функции, все работает так, как ожидалось.
Я нашел решение этой проблемы, которое опишу в ответе ниже, но хотел узнать, не знает ли кто-нибудь, кто более знаком с Eigen внутренности могут объяснить это и / или предложить лучшее решение.
Обновление: Я только что протестировал приведенный выше код на другом компьютере (Linux), используя G CC 6.4.0 а там все нормально работает. Так что это может быть связано с компилятором.