特征参数通过引用传递

时间:2018-03-14 03:26:27

标签: c++ eigen eigen3 pybind11

我在Eigen文档中跟随此页面试图理解特征参数的使用

https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

以下代码按预期工作

true

但是,如果数组的初始声明更改为

#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); 的定义,也会因分段错误而失败。

1 个答案:

答案 0 :(得分:0)

我喜欢看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>,但您不能将可变引用绑定到临时引用。