在Eigen中进行重塑功能

时间:2016-07-10 04:02:55

标签: c++ eigen

这里是Eigen中重塑函数的代码。它有效。

typedef MatrixXd mat;
typedef VectorXd vec;

Map<mat> reshape (vec b, const uint n, const uint m) {
    return Map<mat>(b.data(), n, m);
}

我试图为第一个参数决定正确的类型。

vec & b仍然有效,但我得到了奇怪的错误 const vec & bconst vec b

error: invalid conversion from 'const Scalar* {aka const double*}' to 'Eigen::Map<Eigen::Matrix<double, -1, -1> >::PointerArgType {aka double*}' [-fpermissive]
     return Map<mat>(b.data(), n, m);
                 ~~~~~~^~

我怀疑这是由于可变性以及重塑功能没有分配新内存的事实,但我想学习更详细的解释。

嗯,似乎vec && b是正确的类型,但我的深度不合适。

2 个答案:

答案 0 :(得分:3)

你是对的,这是一个可变性问题。如果您使用const vec&,则只能将其映射到const mat

Map<const mat> reshape (const vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

否则您可以通过映射矩阵修改const vec的组件。它与分配内存无关。

实际上,vecconst vec都是错误的。它们都意味着映射到原始向量的临时副本,其生命在函数调用之后结束,正如Avi Ginsburg所说,导致未定义的行为。

请注意,上述代码仅在输入为Eigen::VectorXd时才正确。

实际上,如果您的输入vec&是表达式,则const vec&b都可能是错误的。使用vec&将无法编译,因为表达式的组件不可变。使用const vec&将强制在函数调用期间将表达式计算为临时const向量,并且您将再次映射到临时向量。

Map<mat> reshape (vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

Map<const mat> reshape_const (const vec& b, const uint n, const uint m) {
    return Map<const mat>(b.data(), n, m);
}

vec a(100), b(100);
Map<mat> c1 = reshap(a, 10, 10);                  // ok
Map<mat> c2 = reshap(a + b, 10, 10);              // error, expression not mutable
Map<const mat> c3 = reshap_const(a, 10, 10);      // ok
Map<const mat> c4 = reshap_const(a + b, 10, 10);  // error, mapping to temp vec

在这种情况下,您需要使用表达式类型作为参数类型,尽管您可能不打算将reshape与表达式一起使用。你可以在这里找到更多细节。

http://eigen.tuxfamily.org/dox-devel/TopicFunctionTakingEigenTypes.html

答案 1 :(得分:2)

这只是一个范围问题。 让我们创建一个MCVE并用它来解释:

#include <Eigen/Core>
#include <iostream>

using namespace Eigen;

typedef MatrixXd mat;
typedef VectorXd vec;

Map<mat> reshapeCopy (vec b, const size_t n, const size_t m) {
    return Map<mat>(b.data(), n, m);
}

Map<mat> reshape (vec &b, const size_t n, const size_t m) {
    return Map<mat>(b.data(), n, m);
}

int main()
{
    vec tr;
    tr.setLinSpaced(4,1,4);
    std::cout << tr << "\n\n";
    Map<mat> m = reshape(tr, 2,2);
    std::cout << m << "\n\n";
    return 0;
}

在Ubuntu输出上使用g ++ 4.9.3:

  

1
  2
  3
  4

     

4.94066e-324 3
  4.94066e-324 4

     

1 3
  2 4

reshapeCopy中,btr副本。它的生命周期一直持续到reshapeCopy函数的末尾。因此,在main中使用时,输出是乱码/未定义的行为。 reshape函数tr通过引用传递,因此b的生命周期与tr一样长,输出符合预期。

kangshiyin指出您使用const vec bconst vec &b定义b Map<mat>为const的函数时,您指出的具体错误是正确的, ie 不可变,返回类型是可变的title__icontains=query