Как изменяется собственный необработанный буфер даже при передаче ссылки на функцию
Я создавал программу на C++ с возможностью взаимодействия с python через необработанный буфер, если быть точным, тупой. И я использовал собственную библиотеку для матричных операций. Потом я обнаружил это очень странное поведение.
Как вы, возможно, знаете, ndarray в numpy - это главная строка, поэтому я создал матричную карту основных строк в моей программе на C++, чтобы обернуть необработанный буфер из PyObject numpy. Тем не менее, все функции в моей программе используют матрицы в главном столбце, в результате эти функции реализуются с помощью константных ссылочных аргументов с типом собственной собственной матрицы столбца. Я заметил, что несмотря на то, что я передаю мажорную матрицу строк в этих функциях, программа работает хорошо, и правильность может быть гарантирована. Тем не менее, я все еще хочу выяснить, почему это происходит
Я распечатал содержимое данных в исходном буфере как основной матрицы строк, так и основной матрицы столбцов в одной функции. И я обнаружил, что расположение данных было как-то изменено. Итак, мой вопрос, как это происходит? Есть ли копия памяти, которая отвечает за это?
Я также написал простую программу на 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
1 ответ
Такое поведение вполне ожидаемо. При звонке void Func(const Mat &m, int dim)
с чем-то другим, чем Mat
объект для первого аргумента, затем он копируется во временный тип Mat
, Это возможно, потому что аргумент является константной ссылкой и существует неявный Matrix
конструктор из любых выражений Эйгена. Точнее, вот что происходит при звонке Func(mat, dim);
:
Mat tmp(mat);
Func(tmp,dim);
tmp.~Mat();
И то и другое tmp
а также mat
представляют одну и ту же матрицу, но с разными порядками хранения.