Я довольно новичок в 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;
}
метод 1:
Я начал с простой передачи значений в функцию, затем в функцию, сохраняя эти значения в стандартном:: 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
Вывод карт явно не тот, чтожелательно.Кроме того, карты не должны указывать на один и тот же вектор.
метод 2:
Затем я попытался вернуть 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 здесь не происходит.
метод 3:
Наконец я попытался вернуть вектор, а затем инициализировать карту в следующей строке:
x_m3:
1 3
2 4
y_m3:
5 7
6 8
x_m3.data():
0xaea150
y_m3.data():
0xaea180
Это дает желаемый результат, и ядумаю NRVO на std :: vector является причиной, почему.
попытка понять результаты:
Как уже упоминалось, я думаю, что определяющим фактором того, дает ли метод желаемые результаты, является то, происходит ли NRVO или нет.
Для третьего метода я знаю, что NRVO происходит для std :: vector.
Для второго метода я вижу, что, возможно, данные в векторе уничтожаются, когда функция выходит так, что одинв вызывающей функции остается «висячий вектор» (поэтому я предполагаю, что NRVO для std :: vector происходит только тогда, когда вы явно устанавливаете функцию return равной вектору того же типа, что и return ??).И поскольку данные были уничтожены, те же адреса могут использоваться для второго вызова функции для хранения двойников (что постигнет та же участь).
Итак, я думаю, что мой главный вопрос (помимо пояснения только что сделанных заявлений): разве NRVO не работает для собственных карт?Есть ли какая-то особая причина для этого?
Я использую eigen 3.5, c ++ 11 с g ++
Заранее спасибо