代码之家  ›  专栏  ›  技术社区  ›  itQ

指向特征::映射对象的C++特征指针

  •  3
  • itQ  · 技术社区  · 7 年前

    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?
    
    };
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   ggael    7 年前

    首先,这里不需要使用指针,因为Map本质上已经是一个指针,所以它会更简单,所以用 placement new . 尽管如此,您当前的设计需要在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<const VectorXd> const Map<VectorXd> 就像你最初的问题一样。