我最近一直在使用 Eigen,虽然一切都有意义,但我只是对库如何摆脱它使用的奇怪语法有点困惑。
例如,在定义矩阵时,您应该执行以下操作:
MatrixXd m(2,2); //defines a 3 x 4 matrix
m(0, 0) = 1;
m(0, 1) = 2;
m(1, 0) = 3;
m(1, 1) = 4;
或者你可以做这样的事情:
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << m;
虽然这些命令在概念上对我来说是有意义的,但我很好奇它们对编译器的意义。我认为<<用于位移,括号符号用于输入参数函数或其他东西,而不是用于解析像数组这样的矩阵结构。
我使用C++的时间还不够长,无法理解所有这些语法,但我想知道 Eigen 的作者是否以某种方式定义了自定义语法或其他东西。
在这两个代码块中,都有一些运算符重载。
在第一个代码块中,行MatrixXd m(2,2);
创建对象,因为它是声明,并且我们在那里有MatrixXd
的类型。因此,语法m(i, j)
必须是对接收两个参数的构造函数的调用(只要其他参数具有默认值,它也可以是接收更多参数的构造函数(。
第一个代码块中的其他行不调用构造函数,因此语法m(i, j)
意味着调用operator()(i, j)
的实现。从技术上讲,类似于operator()(int i, int j)
. 综上所述,第一个代码块只需要一个运算符重载,而且是人们经常实现的一个。
第二个代码块对我来说更像是魔术。部分m << Number
意味着m
的类型,即Matrix3f
,对operator<<
有重载。然后我认为任何返回1operator<<
的类型都必须具有逗号运算符的实现才能允许1, 2, 3, ...
部分。逗号运算符很少使用,它是恕我直言重载的最晦涩的运算符。总之,第二个代码块需要两个运算符重载,其中一个更模糊。是的,这是魔术。
1它可以是对m
的引用,因此是Matrix3f
的,甚至可以是由 Eigen 作者创建的完全不同的类型,以允许这种漂亮的语法初始化矩阵。
我不知道 Eigen,我认为你应该看看这些运算符是如何实现的。但是,一个小玩具示例可能有助于了解正在发生的事情。
#include <array>
#include <iostream>
struct my_matrix {
std::array< std::array< int,10>,10> data;
int& operator()(size_t i,size_t j) { return data[i][j]; }
const int& operator()(size_t i,size_t j) const { return data[i][j]; }
};
int main (){
my_matrix x;
x(1,1) = 42;
std::cout << x(1,1);
}
重载operator()
相当灵活,因为它允许参数的数量。返回对data
元素的引用允许用户修改非常量my_matrix
的元素。为了还允许访问const my_matrix
的元素(不修改它们(,运算符还存在const
过载。与重载operator()
类似,<<
也是一个可以重载做不同事情的运算符。有关运算符重载的更多信息,请参阅此处和此处。