2

如何通过引用将特征矩阵 A 传递给函数,然后窃取 A 的所有权?

我正在为 Python 编写一个 C++ 扩展,它接受两个std::vector<Eigen::Ref<Mat> >并返回一个std::vector<Mat>. 返回向量的每个元素可以是输入向量中引用的新矩阵或旧矩阵。

Eigen::Ref来自 pybind11 的示例在此处(pybind11 doc)提到了 C++ 和 Python 之间的传递引用。

我尝试修改一个示例(来自旧的错误报告)。但是源没有移动到目标。这是因为源矩阵最后不是空的。

测试:

#include <iostream>
#include <eigen3/Eigen/Dense>

typedef Eigen::MatrixXd Mat;

Mat func(Eigen::Ref<Mat> ref) {
    Mat target(std::move(ref));
    return target;
}

int main() {
  const std::size_t n = 2;
  Mat source = Mat::Zero(n, n);
  Mat target = func(source);
  std::cout << "source\n" << source << "\n";
  std::cout << "target\n" << target << "\n";
  return 0;
}

结果:

source
0 0
0 0
target
0 0
0 0
4

3 回答 3

2

这是不可能的,因为它的内存布局Ref<MatrixXd>比它更通用MatrixXd,它甚至不拥有它引用的数据!因此,您唯一的解决方案是通过MatrixXd&.

于 2018-01-28T12:57:52.330 回答
1

ref在你的函数内部是一个局部变量。可以动一下,没问题。但是您不能窃取所有权,因为它是按值传递的,您无权访问该对象,因为它存在于调用者的工作区中。此外,您正在移动对 的构造函数的引用Mat,这将简单地通过复制创建一个新矩阵(我假设,因为您不能将一种类型的对象移动到不同类型的对象)。

您看到发生的事情是因为在调用者的工作区中ref共享数据source。这是两个指向相同数据的不同对象。

如果您要返回引用对象(而不是像您那样创建一个用引用对象初始化的新矩阵),那么引用可能会比引用的原始对象寿命长,并造成麻烦。

于 2018-01-28T03:44:55.873 回答
0

这在 C++ 中有效:

测试:

#include <iostream>
#include <eigen3/Eigen/Dense>
#include <vector>

typedef Eigen::MatrixXd Mat;

void print_mats(std::string const& s, const std::vector<Mat>& v) {
    std::cout << s << "\n";
    for (int i = 0; i < v.size(); ++i) {
        std::cout << "matrix #" << i << "\n";
        std::cout << v[i] << "\n";
    }
}

std::vector<Mat> func(std::vector<Mat>& source) {
    std::vector<Mat> target;
    target.emplace_back(std::move(source[0]));
    return target;
}

int main() {
    const std::size_t n = 2;
    std::vector<Mat> source;
    // can't move Mat::Zero(n, n), which is a const expression.
    // no need for source.emplace_back(std::move(Mat::Zero(n, n)));
    source.emplace_back(Mat::Zero(n, n));
    print_mats("source before", source);
    std::vector<Mat> target = func(source);
    print_mats("source after", source);
    print_mats("target", target);

    return 0;
}

结果:

source before
matrix #0
0 0
0 0
source after
matrix #0

target
matrix #0
0 0
0 0
于 2018-01-29T16:55:14.143 回答