Would the following example create a dangling reference? (Since the vector<int>
is local in the function and the MatrixXi
is using a reference to this data). Also considering the Foo constructor takes a reference to the MatrixXi
.
#include <Eigen/Dense>
#include <Eigen/Core>
using Eigen::MatrixXi;
static Eigen::MatrixXi CreateMatrix()
{
std::vector<int> data(4);
data = { 1, 2, 3, 4 };
Eigen::MatrixXi mat = Eigen::Map<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(&data[0], 2, 2);
return mat;
}
class Foo
{
public:
const MatrixXi matrix;
Foo(const MatrixXi &matrix) : matrix(matrix) {}
void Bar() {
std::cout << matrix << std::endl;
}
};
int main()
{
Foo test(CreateMatrix());
test.Bar();
Foo* test2 = new Foo(CreateMatrix());
test2->Bar();
std::cin.get();
delete test2;
}
EDIT:
Added the delete test2
to free the memory.
EDIT2:
The actual creation of the MatrixXi in the real problem is based on a parameter of the function and looks like this (C++/CLI):
static Eigen::MatrixXi CreateMatrix(MathNet::Numerics::LinearAlgebra::Matrix<float>^ data)
{
int length = data->RowCount * data->ColumnCount;
std::vector<int> data_out(length);
for (size_t i = 0; i < data->RowCount; i++)
{
for (size_t j = 0; j < data->ColumnCount; j++)
{
data_out[i * data->ColumnCount + j] = data[i, j];
}
}
Eigen::MatrixXi mat = Eigen::Map<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(&data_out[0], data->RowCount, data->ColumnCount);
return mat;
}
UPDATE:
To prove the answer from davidhigh is correct I've written the following test:
int main()
{
std::vector<int> data = { 1, 2, 3, 4 };
auto map = Eigen::Map<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(&data[0], 2, 2);
Eigen::MatrixXi mat = map;
data[0] = 5;
std::cout << "mat:\n" << mat << std::endl;
std::cout << "map:\n" << map << std::endl;
std::cin.get();
}
This gives console output:
mat:
1 2
3 4
map:
5 2
3 4
So no dangling reference since mat is no longer connected to data (while map is).
Ok, as the status of this thread became a bit confusing, I'll add another answer and detail what I already wrote in the comments.
It is ok to return a MatrixXi
inside the function CreateMatrix
and return it. You perform the creation of the matrix via copying from an Eigen::Map
, which is also ok.
In your simple example, you could get around the Map
by directly initializing the MatrixXi
, e.g. via operator<<
. In more general scenarios, maybe all you got is a vector, and then your approach is again ok.
It's crucial that you return the MatrixXi
here. If you would return the Map
object, this will -- in general -- lead to a dangling reference. Then, for example, if you call operator()
outside, the Map
wants to access the vector which is already destructed at exit of CreateMatrix()
. (Actually, in your special example, it would work, as you directly use the result to create a Foo
, which is again storing the Map
inside a matrix -- still, it's not a good idea to write a function that's so error prone).
Final point: don't do this raw pointer stuff with test2
which you did in your main function. There's absolutely no use for it here. Use RAII, which is basically your first approach in main.