Sanity check that constructing a parameter inline circumvents aliasing functions with Eigen

Alec Jacobson

July 27, 2015

weblog/

Suppose I have a function with Eigen types as inputs and outputs:

void aliasing_function(
  const Eigen::MatrixXd & A,
  Eigen::MatrixXd & B)
{
  for(int i = 0;i<B.rows();i++)
  {
    B.row(i) = A.row(A.rows()-i-1);
  }
}

This function is dangerous despite the const on the input parameter A because if A and B reference the same place in memory, writing to B will also write onto what this function thinks is A. Usually this is undesirable and it's called aliasing. For example consider calling with the same input as output:

aliasing_function(C,C);

Supposing that I can't/won't/refuse to change the implementation of aliasing_function, here's proof that you can avoid aliasing problems by using the copy constructor of the Eigen type directly in the parameter (avoiding the explicitly named temporary variable, but still costing a copy probably). The call above is replaced with:

aliasing_function(Eigen::MatrixXd(C),C);

To have a tangible example:

int main()
{
  using namespace std;
  Eigen::MatrixXd C = (Eigen::MatrixXd(3,3)<<1,2,3,4,5,6,7,8,9).finished();
  cout<<"C: "<<endl<<C<<endl;
  aliasing_function(Eigen::MatrixXd(C),C);
  cout<<"C: "<<endl<<C<<endl;
  aliasing_function(C,C);
  cout<<"C: "<<endl<<C<<endl;
}

This outputs:

C: 
1 2 3
4 5 6
7 8 9
C: 
7 8 9
4 5 6
1 2 3
C: 
1 2 3
4 5 6
1 2 3

The last print out shows the effect of aliasing.