我正在构建一个C ++程序,它具有通过原始缓冲区与python进行交互的能力,具体而言是numpy。我正在使用特征库进行矩阵运算。然后我发现了这种非常奇怪的行为。
你可能知道,numpy中的ndarray是row major,所以我在我的C ++程序中创建了一个行主矩阵映射,以便从Numpy的PyObject包装原始缓冲区。但是,我的程序中的所有函数都使用了列major中的矩阵,因此,这些函数是使用具有列主要特征矩阵类型的const引用参数实现的。我注意到即使我在这些函数中传递行主矩阵映射,程序运行良好,并且可以保证正确性。尽管如此,我仍然想弄清楚为什么会发生这种情况
我在一个函数中打印出行主矩阵图和列主矩阵的原始缓冲区内的数据内容。我发现数据布局已经以某种方式改变了。所以我的问题是这是怎么发生的?是否有一个内存副本负责?
我还写了一个简单的C ++程序,完全按照我上面的描述。任何人都可以将其作为此问题的演示。
#include <Eigen/Dense>
#include <Eigen/Core>
#include <iostream>
using MatMap = Eigen::Map< Eigen::Matrix<int, Eigen::Dynamic,
Eigen::Dynamic, Eigen::RowMajor> >;
using Mat = Eigen::Matrix<int, Eigen::Dynamic,
Eigen::Dynamic, Eigen::ColMajor>;
void Func(const Mat &m, int dim) {
// Print internal raw buffer of m
std::cout << std::endl;
for (int i = 0; i < dim * dim; i++)
std::cout << *(m.data() + i) << std::endl;
std::cout << std::endl;
}
int main() {
int dim = 3;
// Raw buffer
int *raw = new int[dim * dim];
for (int i = 0; i < dim * dim; i++)
raw[i] = i;
// Matrix Map
MatMap mat(nullptr, 0, 0);
// Create
new (&mat) MatMap(raw, dim, dim);
// Print raw buffer of mat
std::cout << std::endl;
for (int i = 0; i < dim * dim; i++)
std::cout << *(mat.data() + i) << std::endl;
std::cout << std::endl;
// Function call
Func(mat, dim);
return 0;
}
上述程序的结果如下:
0
1
2
3
4
5
6
7
8
0
3
6
1
4
7
2
5
8
答案 0 :(得分:2)
完全可以预料到这种行为。当使用与第一个参数的void Func(const Mat &m, int dim)
对象不同的内容调用Mat
时,会将其复制到Mat
类型的临时对象中。这是可能的,因为参数是一个const引用,并且存在来自任何Eigen表达式的隐式Matrix
构造函数。更确切地说,这是调用Func(mat, dim);
时发生的事情:
Mat tmp(mat);
Func(tmp,dim);
tmp.~Mat();
tmp
和mat
都代表相同的矩阵,但存储顺序不同。