2017-09-05 158 views
2

是否可以定義指向特徵:: Map對象的指針?原始代碼是非常複雜,但這裏是我想實現(僞代碼)C++特徵指針指向Eigen :: Map <Eigen :: VectorXd>對象

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? 

}; 

回答

0

所有沒有必要在這裏使用指針,因爲地圖是已經基本上是一個指針,所以它會更簡單,從而更新第一與placement new的地圖對象。儘管如此,當前的設計需要在testfunction1中進行分配,並且在testfunction2中進行了重新分配,以防其被分配,這並不安全。通過把「一些計算」功能內,以便更好地採用功能設計(或命名拉姆達),使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); 
}; 

如果你真的想保持當前的邏輯,那麼這裏是一個自使用放置新-contained例如:

#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; 
} 

這是非常不好的,因爲如果一個異常被要求testFunction1返回一個VectorXd(或任何處理內存使用X時,你可以手動解決方法內存管理提出它可能會泄漏分配/取消分配)並在主函數中進行新的放置N:

#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>在你最初的問題。

+0

感謝您的回答。這是我當前的代碼正在做的事情,但它使閱讀變得困難,因爲if語句需要不同的func,但我會接受你的答案,因爲它可能對其他人有用。然而,我仍然想知道如何聲明一個指向Map的指針<...> – itQ

+0

沒有什麼棘手的,只是聲明'typedef const MapVectorXd ConstMapVectorXd;'然後使用'ConstMapVectorXd *',但是你必須處理複雜的動態內存分配通過新的Map和Map對象本身,這總是容易出錯和內存泄漏。如果您使用[placement new](https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html#title3)修改Map對象本身,您將「僅」必須處理引用數據的分配/釋放,更好,並不令人滿意。 – ggael

+0

您的完整答案只是完美!非常感謝! – itQ