Собственный указатель C++ на объект Eigen::Map<Eigen:: VectorXd>
Можно ли определить указатель на объект 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?
};
1 ответ
Прежде всего, нет необходимости использовать указатели здесь, потому что Map уже по сути является указателем, поэтому было бы проще, поэтому обновите объект Map с помощью размещения 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);
};
Если вы действительно хотите сохранить свою текущую логику, то вот отдельный пример с использованием размещения 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>
как в вашем первоначальном вопросе.