使用block()在分配中使用block()缩小矩阵

Shrink matrix with Eigen using block() in assignment

本文关键字:block 缩小 分配 使用      更新时间:2023-10-16

我有以下代码,通过删除最后一行来缩小特征MATRIXXD。无论如何,这似乎破坏了矩阵。Valgrind也对该代码感到非常沮丧。执行该任务的正确方法是什么?

#include <Eigen/Core>
#include <iostream>
int main() {
    Eigen::MatrixXd A(3, 4);
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 4; j++)
            A(i, j) = i * j + i + j + 5;
    std::cout << "A = n" << A << std::endl;
    A = A.block(0, 0, 2, 4);
    std::cout << "A = n" << A << std::endl;
    return 0;
}

此代码在我的计算机上产生以下输出(注意5变为0)

A = 
 5  6  7  8
 6  8 10 12
 7 10 13 16
A = 
 0  6  7  8
 6  8 10 12

Eigen::Block<...>block()成员函数返回)不做涉及的值的副本,而是作为对矩阵的一部分的引用。您可以用

看到这个
A.block(0, 0, 2, 4) *= 2; // this will change A

因此,只要基础矩阵不重新安置其值,Eigen::Block对象就保持有效,如果您为其分配了不同的几何形状(例如A.block(0, 0, 2, 4)),则该值将其有效。一旦基础矩阵发布了其预分配内存,使用Block对象构成了无用的使用,并导致不确定的行为,并且分配运算符当然会尝试从当时已灭绝的Block。P>

正如您在此期间发现的那样,您可以使用

A.conservativeResize(2, 4);

对于您的特定情况,因为您想向左上角收缩。对于一般情况,您可以使用(例如)

A = A.block(1, 1, 2, 3).eval();

.eval()迫使立即强制进行懒惰评估,在这种情况下,这实际上意味着制作块的临时副本,然后分配给矩阵。有关所有这些的更多详细信息,请参见特征文档。