我应该如何使用Eigen的数据结构?

时间:2015-06-19 17:45:45

标签: c++ eigen

我想知道如何在Eigen中管理数据结构。

更确切地说,我想知道我是否应该将它们作为指针传递,或者它们实际上可能会使用一些智能指针。

例如,以下功能是否有意义:

SparseVector<double> retVector()
{
     SparseVector<Double> vec(3);
     return vec;
}

或者它会有问题,因为vec是一个局部变量,SparseVector不仅仅是vec周围的智能指针包装类吗?

意思是,或许最好使用:

SparseVector<double>* retVector()
{
     SparseVector<Double> *vec = new SparseVector<double>(3);
     return vec;
}

1 个答案:

答案 0 :(得分:1)

比这更复杂。如果我们在讨论任何对象,@ Anycorn是正确的,因为未优化的版本将在返回时在函数中生成对象的深层副本。但是,启用优化后copy elision允许编译器在适当的位置构造返回的对象。这不是Eigen特有的。作为一个例子,我们可以看一个类似于你的函数返回一个特征对象。

Eigen::MatrixXd retMat()
{
    Eigen::MatrixXd inMat = Eigen::MatrixXd::Random(1000,1000);
    std::cout << &inMat << "\t" << inMat.data() << "\t" << *(inMat.data() + rand() * 20) <<  "\n";
    return inMat;
}

Eigen::SparseMatrix<double> retSMat()
{
    Eigen::MatrixXd denseMat = Eigen::MatrixXd::Random(100,100);
    Eigen::SparseMatrix<double> inMat = denseMat.sparseView();
    std::cout << &inMat << "\t" <<  "\n";

    return inMat;
}

int main(int argc, char *argv[])
{
    srand(time(NULL));
    Eigen::MatrixXd outMat(5,5);
    std::cout << "Dense matrix addresses (1):\n";
    std::cout << &outMat << "\t" << outMat.data() << "\n";
    outMat = retMat();
    std::cout << &outMat << "\t" << outMat.data() << "\n\n";

    std::cout << "Dense matrix addresses (2):\n";
    Eigen::MatrixXd outMat2 = retMat();
    std::cout << &outMat2 << "\t" << outMat2.data() << "\n\n";

    std::cout << "Sparse matrix addresses:\n";
    Eigen::SparseMatrix<double> outMatSp = retSMat();
    std::cout << &outMatSp << "\n";
    return 0;
}

在Debug中运行(关闭优化)我们得到:

Dense matrix addresses (1):
00000032B6A8EF58        00000032B6BDB870
00000032B6A8EEA8        00000032B6CDA070        -0.620289
00000032B6A8EF58        00000032B6CDD070

Dense matrix addresses (2):
00000032B6A8EEA8        00000032B7481070        0.157872
00000032B6A8EF88        00000032B7C3F070

Sparse matrix addresses:
00000032B6A8EE60
00000032B6A8EFC0

我们看到没有一个地址是相同的,正如对代码的天真解释所期望的那样。如果启用优化,则图片略有不同:

Dense matrix addresses (1):
0000009BEB0AF700        0000009BEB14BBF0
0000009BEB0AF780        0000009BEB2C1040        0.862606
0000009BEB0AF700        0000009BEBA7B040

Dense matrix addresses (2):
0000009BEB0AF718        0000009BEB2CC040        -0.601367
0000009BEB0AF718        0000009BEB2CC040

Sparse matrix addresses:
0000009BEB0AF740
0000009BEB0AF740

我们看到在情况(2)和稀疏矩阵示例中,对象的地址是相同的,表示对象是在目标对象地址中创建的。请注意,这与move semantics不同,后者需要书写move constructor(我很确定Eigen尚未实现)。

关于Eigen,由于它的lazy evaluation,一些表达式立即not evaluated,而是在被认为是谨慎/必要时。在简单示例中不是这种情况,但如果示例中有一些计算,则可以是这种情况。在这种情况下,返回的对象可能是在结果对象中追加/评估的表达式树。