Собственные параметры, передаваемые по ссылке

Я следую за этой страницей в документации 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> но вы не можете связать изменчивую ссылку с временной.

Другие вопросы по тегам