我对C++和它的特征库很陌生。当从函数返回一个特征映射(指向std::vector),或者从函数返回一个std::vector,然后对其应用特征映射时,我遇到了一些我认为有点奇怪的行为。我认为这与命名返回值优化(NRVO)有关。
我已经用三种方法做了这件事。前两种方法给出了不希望的结果,而第三种方法给出了我想要的结果(参见下面的输出)。下面是一个说明这三种方法的最小工作示例:
int main(){
double i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5, i6 = 6, i7 = 7, i8 = 8;
//method 1
Eigen::Map< Eigen::MatrixXd > x_m1 = get_map_test(i1, i2, i3, i4);
Eigen::Map< Eigen::MatrixXd > y_m1 = get_map_test(i5, i6, i7, i8);
//method 2
Eigen::Map< Eigen::MatrixXd > x_m2(get_vec_test(i1, i2, i3, i4).data(), 2, 2);
Eigen::Map< Eigen::MatrixXd > y_m2(get_vec_test(i5,i6,i7,i8).data(), 2, 2);
//method 3
std::vector<double> x_v3 = get_vec_test(i1, i2, i3, i4);
std::vector<double> y_v3 = get_vec_test(i5, i6, i7, i8);
Eigen::Map< Eigen::MatrixXd > x_m3(x_v3.data(), 2, 2);
Eigen::Map< Eigen::MatrixXd > y_m3(y_v3.data(), 2, 2);
} //end main
//used in method 1
Eigen::Map< Eigen::MatrixXd > get_map_test(double a, double b, double c, double d) {
std::vector<double> t_v = {a,b,c,d};
return Eigen::Map< Eigen::MatrixXd >(t_v.data(), 2, 2);
}
//used in methods 2 and 3
std::vector<double> get_vec_test(double a, double b, double c, double d) {
std::vector<double> t_v = {a,b,c,d};
return t_v;
}
我首先简单地将值传递给一个函数,然后在函数中,将这些值存储在std::vector中,并返回指向该向量的特征映射(特征矩阵的)。
然后,我得到了矩阵x_m1和y_m1的值以及它们的。data()值的以下输出:
x_m1:
4.94066e-324 7
4.94066e-324 8
y_m1:
4.94066e-324 7
4.94066e-324 8
x_m1.data():
0xaea150
y_m1.data():
0xaea150
这些地图的输出显然不是所期望的。此外,地图不应该指向同一个矢量。
接下来,我尝试返回std::vector,并使用它在函数return的同一行中初始化一个映射。
相应的结果是:
x_m2:
4.94066e-324 7
4.94066e-324 8
y_m2:
4.94066e-324 7
4.94066e-324 8
x_m2.data():
0xaea150
y_m2.data():
0xaea150
正如我们所看到的,这导致了同样的结果,但是我可以理解为什么NRVO没有在这里发生。
最后,我尝试返回向量,然后在下面一行初始化映射:
x_m3:
1 3
2 4
y_m3:
5 7
6 8
x_m3.data():
0xaea150
y_m3.data():
0xaea180
这给出了我想要的结果,我猜std::vector上的NRVO就是原因。
如前所述,我认为该方法是否给出所需结果的决定因素是是否发生NRVO。
对于第三种方法,我知道std::vector会发生NRVO。
对于第二种方法,我可以看到,在函数退出时,向量中的数据可能会被销毁,因此在调用函数中留下了一个“悬空向量”(因此,我假设只有当您显式地将函数return设置为与return??相同类型的向量时,才会出现std::vector的NRVO)。并且由于数据被破坏,相同的地址可以用于第二个函数调用来存储双倍(它遭受相同的fate)。
所以我猜我的主要问题(除了澄清我刚才所做的陈述之外)是,NRVO对本征映射不起作用吗?这有什么特别的原因吗?
我用的是本征3.5,C++11和G++
提前致谢
简单看一下
看“方法一”:
Eigen::Map< Eigen::MatrixXd > get_map_test(double a, double b, double c, double d) {
std::vector<double> t_v = {a,b,c,d};
return Eigen::Map< Eigen::MatrixXd >(t_v.data(), 2, 2);
}
您将返回一个
方法2如下所示:
std::vector<double> get_vec_test(double a, double b, double c, double d) {
std::vector<double> t_v = {a,b,c,d};
return t_v;
}
这个函数本身不会发生什么不好的事情。你只是做一个向量你的4倍,并返回它的值。但是,您可以使用它执行以下操作:
Eigen::Map< Eigen::MatrixXd > x_m2(get_vec_test(i1, i2, i3, i4).data(), 2, 2);
从
当然,方法3完全避免了这一点,因为您使用这些向量在
您看到的问题与NRVO无关,而是关于在C++中理解对象生命期的问题。您的代码试图通过指向不再存在的对象的指针对这些对象执行操作。