这里是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 & b
或const 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
是正确的类型,但我的深度不合适。
答案 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的组件。它与分配内存无关。
实际上,vec
和const 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
44.94066e-324 3
4.94066e-324 41 3
2 4
在reshapeCopy
中,b
是tr
的副本。它的生命周期一直持续到reshapeCopy
函数的末尾。因此,在main
中使用时,输出是乱码/未定义的行为。 reshape
函数tr
通过引用传递,因此b
的生命周期与tr
一样长,输出符合预期。
kangshiyin指出您使用const vec b
或const vec &b
定义b
Map<mat>
为const的函数时,您指出的具体错误是正确的, ie 不可变,返回类型是可变的title__icontains=query
。