Search code examples
c++eigeneigen3

Constructing Eigen::Array from Eigen::Map, how does it work?


In my project I have written the following code:

Eigen::ArrayXf foo(const Eigen::ArrayXcf &src)
{
    auto * output = new float[src.size()];
    //Fill the data here
    return Eigen::Map<Eigen::ArrayXf>(output, src.size());
}

Note that the stuff constructed in return statement is an Eigen::Map, but compiler does not complain anything so there must be a conversion. Therefore I have the following questions:

  1. How does this conversion happen? By making a deep copy of original data or just changing ownership?
  2. Is this code OK? Does it cause undefined behaviours or memory leaks?
  3. If I want the returned Eigen::Array owns the data in *output instead of copying it, and release this block of memory on destruction, how can I achieve this? At here I noticed Eigen::Array and Eigen::Matrix can be initialized with raw data pointer, but it seems only work on fixed size arrays and matrices. This function is going to be called frequently so I do care about the efficiency.

Solution

  • ArrayXf has an implicit constructor from Map<ArrayXf> (in fact from any ArrayBase<...> object) which makes a deep copy of the content. From Eigen's point of view your code is safe, however you leak memory, since you never de-allocate the float* output data. Generally, new should be avoided or at least encapsulated when writing clean C++ code.

    You can make your code much easier, by directly allocating the Array object you want to return later (there won't be a copy on any non-ancient C++ compiler, due to RVO (return value optimization)):

    Eigen::ArrayXf foo(const Eigen::ArrayXcf &src)
    {
        Eigen::ArrayXf output_array(src.size());
        float * output = output_array.data();
        //Fill the data here
        return output_array;
    }
    

    If you want to avoid memory allocation (inside the function) entirely, you need to elaborate at what place the memory shall actually be allocated. You could just construct an Array object at that place and pass it by reference to your function (or make it a member variable of a class which has foo as a member function).