如何通过引用将特征矩阵A传递给函数,然后窃取A?
的所有权我正在为Python编写一个C ++扩展,它接收两个std::vector<Eigen::Ref<Mat> >
并返回std::vector<Mat>
。返回矢量的每个元素可以是输入矢量中引用的新矩阵或旧矩阵。
pybind11的例子提到了C ++和Python之间的引用,Eigen::Ref
在这里(pybind11 doc)。
我尝试修改一个例子(来自old bug report)。但是源不会移动到目标。这是因为源矩阵最后不是空的。
测试:
#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
答案 0 :(得分:2)
这是不可能的,因为Ref<MatrixXd>
的内存布局比MatrixXd
更通用,它甚至不拥有它引用的数据!因此,唯一的解决方案是传递MatrixXd&
。
答案 1 :(得分:1)
ref
是一个局部变量。你可以移动它,没关系。但是你无法窃取所有权,因为它通过价值传递,你无法访问调用者工作区中存在的对象。此外,您正在将引用移动到Mat
的构造函数,它将简单地通过复制创建一个新矩阵(我认为,因为您无法将一种类型的对象移动到另一种类型的对象)。
您看到的情况是因为ref
在来电者的工作区中与source
共享数据。这是两个指向相同数据的不同对象。
如果你要返回引用对象(而不是像你那样创建一个用引用对象初始化的新矩阵),那么引用可能比引用的原始对象更长,并且会引起麻烦。
答案 2 :(得分: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