Как изменяется собственный необработанный буфер даже при передаче ссылки на функцию

Я создавал программу на 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 представляют одну и ту же матрицу, но с разными порядками хранения.

Другие вопросы по тегам