代码之家  ›  专栏  ›  技术社区  ›  schrödinbug

初始化对结构中矩阵元素的引用

  •  0
  • schrödinbug  · 技术社区  · 6 年前

    我有一个表示三维位置的结构。有时可以方便地访问各个组件,有时也可以方便地将所有组件作为向量(物理向量而不是std::vector)访问,我使用的是本征线性代数库。因为只有三个元素(x,y,z),而且永远都只有三个元素,那么拥有三个元素的结构有什么问题吗? double& 是指本征矩阵的元素吗?即。:

    using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
    
    struct EnuPosition
    {
      EnuPosition(): pos(ColumnVector3::Zero()), east(pos[0]), north(pos[1]), up(pos[2]) {}
    
      EnuPosition(double east, double north, double up): pos((ColumnVector3() << east, north, up).finished()),
        east(pos[0]), north(pos[1]), up(pos[2]) {}
    
      EnuPosition(const ColumnVector3& position): pos(position), east(pos[0]), north(pos[1]), up(pos[2]) {}
    
      EnuPosition(const EnuPosition& enu):pos(enu.pos), east(pos[0]), north(pos[1]), up(pos[2]) {}
    
      EnuPosition& operator=(const EnuPosition& enu)
      {
        this->pos = enu.pos;
        return *this;  
      }
    
      ColumnVector3 pos;
      double& east;
      double& north;
      double& up;
    };
    

    它编译良好,在g++5.5上没有警告 -Wall -Wextra -pedantic 在用例中,我可以想到:

    int main ()
    {
      EnuPosition enu{12.5, 34.2, 99.2};
      std::cout << "east: " << enu.east
            << " north: " << enu.north 
            << " up: " << enu.up
            << std::endl;
    
      ColumnVector3 x;
        x << 2.0,3.0,4.0;
    
      enu.pos = x;
    
      std::cout << "east: " << enu.east
            << " north: " << enu.north 
            << " up: " << enu.up
            << std::endl;
    
      Eigen::MatrixXd y;
      y.resize(3,1);
    
      y << 7.6,8.7,9.8;
    
      enu.pos = y;
    
      std::cout << "east: " << enu.east
          << " north: " << enu.north 
          << " up: " << enu.up
          << std::endl;
    
      Eigen::Matrix<double,3,3> R;
    
      enu.east = 1;
      enu.north = 1;
      enu.up = 1;
    
      R << 1,2,3,4,5,6,7,8,9;
    
      enu.pos = (R * enu.pos).eval();
    
      std::cout << "east: " << enu.east
        << " north: " << enu.north 
        << " up: " << enu.up
        << std::endl;
    
      EnuPosition enu2 = enu;
      std::cout << "east: " << enu2.east
        << " north: " << enu2.north 
        << " up: " << enu2.up
        << std::endl;
    }
    

    就像我说的,它是有效的,我只是好奇它是否合法,是否不依赖未定义的行为等,或者是否还有其他问题需要认识?

    1 回复  |  直到 6 年前
        1
  •  1
  •   chtz    6 年前

    添加副本分配后,您的代码应该是安全的。

    但是,如果你对写作没问题的话 east() 而不是 east 在您的代码中,一个稍微优雅一点的解决方案可能是:

    using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
    
    struct EnuPosition : public ColumnVector3
    {
      EnuPosition(): ColumnVector3(ColumnVector3::Zero()) {}
    
      EnuPosition(double east, double north, double up): ColumnVector3(east, north, up) {}
      template<class X> 
      EnuPosition(const X& other): ColumnVector3(other) {}
    
      double&       east()        {return this->x();}
      double const& east() const  {return this->x();}
      double&       north()       {return this->y();}
      double const& north() const {return this->y();}
      double&       up()          {return this->z();}
      double const& up() const    {return this->z();}
    };
    

    如果你故意不想继承,你当然可以把 ColumnVector3 作为会员。