【问题标题】:C++ eigen pointer to a Eigen::Map<Eigen::VectorXd> object指向 Eigen::Map<Eigen::VectorXd> 对象的 C++ 特征指针
【发布时间】:2017-09-05 17:27:49
【问题描述】:

是否可以定义指向 Eigen::Map 对象的指针?原始代码非常复杂,但这是我想要实现的(伪代码)

void testfunction1(... XPtr){
  // XPtr is a pointer
  // create a vector, map it to a Map object and make XPtr point to the latter

  VectorXd Xnew(9);
  Xnew <<  10, 20, 30, 40, 50, 60, 70, 80, 90;
  Map<VectorXd> XnewMap(Xnew.data(), 9); 

  // make XPtr point to XnewMap so that Xnew data can be 
  // accessed outside testfunction1()
  // ... how? I suspect this to involve some dynamic memory allocation
};

void testfunction2(bool yes){
  // main function

  VectorXd XR(9);
  XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
  const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed

  // create a pointer to X, say XPtr
  // ... how?

  if(yes){ // make XPtr point to XnewMap which is defined in testfunction1()
     testfunction1(XPtr);
   };

  //... some computations

  // make XPtr point again to X
  // ... how?

};

【问题讨论】:

    标签: c++ pointers eigen dynamic-allocation


    【解决方案1】:

    首先这里不需要使用指针,因为 Map 本质上已经是一个指针,所以用placement new 更新 Map 对象会更简单。尽管如此,您当前的设计将需要在 testfunction1 中进行分配,并在 testfunction2 中重新分配,以防它已被分配,这并不安全。所以最好采用函数式设计,将“一些计算”放在函数(或命名的 lambda)中,让 testfunction1 按值返回:

    VectorXd testFunction1() { return Xnew; }
    
    void testfunction2(bool yes){
      VectorXd XR(9);
      XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
      const Map<VectorXd> X(XR.data(), 9);
    
      auto func = [&] (Eigen::Ref<VectorXd> X) {
        /* some computation */
      }
    
      if(yes) func(testfunction1());
      else    func(X);
    };
    

    如果你真的想保留你当前的逻辑,那么这里有一个使用placement new的独立示例:

    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    using namespace std;
    
    void testfunction1(Map<VectorXd> &XMap){
      double * Xnew = new double[9];
      ::new (&XMap) Map<VectorXd>(Xnew,9);
      XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90;
    };
    
    int main()
    {
      bool yes = true;
    
      VectorXd XR(9);
      XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
      Map<VectorXd> X(XR.data(), 9);
    
      if(yes) testfunction1(X);
    
      // use X ...
      cout << X.transpose() << endl;
    
      // restore X and free memory allocated in testfunction1
      if(yes){
        delete[] X.data();
        ::new (&X) Map<VectorXd>(XR.data(),9);
      }
    
      cout << X.transpose() << endl;
    }
    

    这非常糟糕,因为如果在使用 X 时引发异常,它可能会泄漏。您可以通过要求 testFunction1 返回VectorXd(或任何自行处理内存分配/释放的任何东西)来解决手动内存管理问题并执行主函数中的新位置:

    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    using namespace std;
    
    VectorXd testfunction1(){
      VectorXd Xnew(9);
      Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
      return Xnew;
    };
    
    int main()
    {
      bool yes = true;
    
      VectorXd XR(9);
      XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
      Map<VectorXd> X(XR.data(), 9);
    
      {
        VectorXd X2;
        if(yes) {
          X2 = testfunction1(); // shallow copy thanks to move semantic
          ::new (&X) Map<VectorXd>(X2.data(),9);
        }
    
        // use X ...
        cout << X.transpose() << endl;
    
        // restore X
        ::new (&X) Map<VectorXd>(XR.data(),9);
      }
    
      cout << X.transpose() << endl;
    }
    

    最后,如果X 的内容应该是只读的,那么使用Map&lt;const VectorXd&gt; 而不是const Map&lt;VectorXd&gt;,就像您最初的问题一样。

    【讨论】:

    • 感谢您的回答。这是我当前的代码正在执行的操作,但由于 if else 语句需要不同的函数,因此难以阅读,但我会接受您的回答,因为它可能对其他人有用。但是,我仍然想知道如何声明指向 Map<...> 的指针
    • 没什么棘手的,只要声明typedef const MapVectorXd ConstMapVectorXd;,然后使用ConstMapVectorXd*,但是对于新Map引用的数据和Map对象本身,你必须处理复杂的动态内存分配,即总是容易出错和内存泄漏。如果您使用 placement new 修改 Map 对象本身,您将“仅”需要处理引用数据的分配/解除分配,更好,但不令人满意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2023-01-29
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多