Понимание возврата функции

Я начинающий программист и только кратко рассмотрел анатомию вызова функции (настройка стека и т. Д.). Я могу написать функцию двумя разными способами, и мне интересно, какой (если любой) более эффективен. Это для программы с конечными элементами, поэтому эту функцию можно вызывать несколько тысяч раз. Он использует библиотеку линейной алгебры Aramdillo.

Первый способ:

void Q4::stiffness(mat &stiff)
{
stiff.zeros; // sets all elements of the matrix to zero
// a bunch of linear algebra calculations
// ...
stiff *= h;
}

int main()
{
mat elementStiffness(Q4__DOF, Q4__DOF);
mat globalStiffness(totalDOF, totalDOF);
for (int i = 0; i < reallyHugeNumber; i++)
{
elements[i].stiffness(&elementStiffness, PSTRESS);
assemble(&globalStiffness, &elementStiffness);
}
return 0;
}

Второй способ:

mat Q4::stiffness()
{
mat stiff(Q4__DOF, Q4__DOF); // initializes element stiffness matrix
// a bunch of linear algebra calculations
// ...
return stiff *= h;
}

int main()
{
mat elementStiffness(Q4__DOF, Q4__DOF);
mat globalStiffness(totalDOF, totalDOF);
for (int i = 0; i < reallyHugeNumber; i++)
{
elementStiffness = elements[i].stiffness(PSTRESS);
assemble(&globalStiffness, &elementStiffness);
}
return 0;
}

Я думаю, что я спрашиваю: использование второго способа mat stiff толкнул в стек, а затем скопировал в elementStiffness? Потому что я представляю, что матрица, помещаемая в стек, а затем копируемая, намного дороже, чем передача эталонной матрицы и установка ее элементов в ноль.

3

Решение

Передача переменной по ссылке и выполнение вычислений для этой переменной намного дешевле. Когда c ++ возвращает переменную, он в значительной степени копирует ее дважды.

Сначала внутри функции, а затем она вызывает конструктор копирования или оператор присваивания, в зависимости от того, присваивается ли значение новой переменной или существующей переменной, для инициализации переменной. Если у вас есть пользовательская переменная с длинным списком внутренних переменных состояния, то эта операция присваивания займет большую часть времени обработки оператора.

РЕДАКТИРОВАТЬ # 1: я забыл о c ++ 11 и std :: move. Многие компиляторы могут оптимизировать подобные функции, поэтому они могут использовать std :: move и вместо копирования lvaue могут копировать значение r, которое является просто местом в памяти.

3

Другие решения

На первый взгляд, я думаю, что второй способ будет намного дороже, поскольку он создает новый мат и копирует его в стек при каждом вызове. Конечно, это немного зависит от того, как часто конструкция ковра происходит первым способом.

Тем не менее, я думаю, что лучшее, что нужно сделать, — это провести эксперимент и убедиться в этом (согласившись с предложением провести исследование).

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector