Собственные параметры, передаваемые по ссылке
Я следую за этой страницей в документации Eigen, пытаясь понять использование параметров Eigen
https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
Следующий код работает как положено
#include <iostream>
#include <Eigen/Dense>
// a - nonwriteable, b - writeable
void eigen_reference_class(
const Eigen::Ref<const Eigen::Array<double,
Eigen::Dynamic, 3> >& a, Eigen::Ref<Eigen::Array<double, Eigen::Dynamic, 3> > b) {
b = 2 * a;
}
void eigen_reference(const Eigen::Array<double, 1, 3>& a, Eigen::Array<double, 1, 3>& b) {
b = 2*a;
}
template<typename Derived>
void eigen_template(const Eigen::PlainObjectBase<Derived>& a, Eigen::PlainObjectBase<Derived>& b) {
b = 2*a;
}
int main()
{
Eigen::Array<double, 1, 3> a, b, c, d;
a << 1, 2, 3;
eigen_reference_class(a, b);
eigen_reference(a, c);
eigen_template(a, d);
std::cout << "a : \n" << a << std::endl;
std::cout << "b: \n" << b << std::endl;
std::cout << "c: \n" << c << std::endl;
std::cout << "d: \n" << d << std::endl;
}
Однако, если первоначальное объявление для массивов изменяется на
Eigen::Array<double, Eigen::Dynamic, 3> a, b, c, d;
Тогда программа либо не сможет скомпилировать следующее:
error: invalid initialization of non-const reference of type ‘Eigen::Array<double, 1, 3>&’ from an rvalue of type ‘Eigen::Array<double, 1, 3>’
eigen_reference(a, c);
Или потерпит неудачу с ошибкой сегментации, даже если только определение a
хранится.
1 ответ
Мне нравится смотреть на что int
делает в таких ситуациях, потому что это помогает мне понять более сложные вещи, происходящие в этом случае легче.
Представь, что у тебя есть struct
держа int
который неявно преобразуется в int
, так что вы можете использовать его вместо int
, вот так:
struct Integer {
int m_int;
operator int() { return m_int; }
};
Теперь определите две функции, одна из которых принимает int const &
и один берет int &
,
void const_ref(int const &) {}
void ref(int &) {}
Если мы используем регулярное целое число в этих функциях, то нет никаких сюрпризов.
int j = 3;
const_ref(j);
ref(j);
Но если мы используем Integer
вместо этого он больше не компилируется.
Integer i{2};
const_ref(i);
ref(i);
Ошибка что-то вроде
error: no matching function for call to 'ref'
ref(i);
^~~
note: candidate function not viable: no known conversion from 'Integer' to 'int &' for 1st argument
void ref(int &) {}
^
1 error generated.
Теперь вопрос в том, почему const_ref
работать, но ref
не делает?
В призыве к const_ref
что происходит, что оператор преобразования в int
называется, который возвращает временный int
к которому мы можем привязать постоянную ссылку. Мы не можем привязать изменяемую ссылку к этому временному объекту, потому что это может привести к странным последствиям. Представьте, что функция ref
изменяет аргумент, но в этом случае он будет модифицировать временный и ничего не будет записано в оригинал Integer
который вы передали... гарантированная ошибка.
В вашем коде это то же самое. Eigen::Array<double, Eigen::Dynamic, 3>
может неявно преобразовать в Eigen::Array<double, 1, 3>
но вы не можете связать изменчивую ссылку с временной.