2016-12-05 2 views
3

Предположим, у меня есть «тяжелая» запись, например, содержащая массивы динамических массивов с кратным числом. Я заявляю это так:Функция должна возвращать запись или указатель?

PMyHugeRecord^ = TMyHugeRecord; 
TMyHugeRecord = record 
    AFirstArray: TSingleDynArray; 
    // many many others 
    ... 
    ALastArray: TSingleDynArray; 
end; 

Хотя обработка происходит в функции, если результат функции наберется как указатель, или она может возвращать переменную запись?

function MyFunctionWhichCalculates: TMyHugeRecord; 
// or 
function MyFunctionWhichCalculates: PMyHugeRecord; 

Я имею в виду производительность, особенно, чтобы избежать переполнения стека. Другими словами, возвращает ли функция результат по ссылке или по значению?

+0

Просто, чтобы указать, что запись, которую вы описали, может быть не такой «тяжелой», как вы думаете. Динамические массивы распределяются по куче и подсчету ссылок. Ваша структура записи содержит «светлые» ссылки на массивы. Аналогично для строк по умолчанию (длинные строки). Однако, если у вас есть фиксированные массивы размера, ваша структура может быть большой. Вы можете использовать 'SizeOf (...)' для определения размера вашего массива. –

+0

Вы правы, и мой пример был не лучшим. Действительно, мои записи могут представлять собой набор различных типов данных, включая массивы фиксированного размера и даже другие записи. Я, возможно, вызвал «огромный» термин, но я всегда заинтересован в оптимизации моего кода. – paradise

+0

Единственный надежный способ оптимизации вашего кода - использовать комбинацию бенчмаркинга и профилирования и проверить разницу в конкретных изменениях. Интуиция часто может вводить в заблуждение. Я не могу подчеркнуть, что вы легко сохраняете большую часть своего кода, чтобы было спокойно *** безопасно *** настраивать свой код в тех местах, где вам нужно точно настроить производительность. –

ответ

9

Вы можете вернуть запись. Это не имеет значения, если это «тяжелый» или нет, так как в действительности, он будет принят в качестве опорного параметра, другими словами , как будто ты заявил:

procedure MyFunctionWhichCalculates(var Result: TMyHugeRecord); 

Не возвращает указатель , даже если вы выделили запись с New(), потому что это оставляет пользователю бремя Dispose() - запись записи через указатель. Это не проблема (но все еще бремя) в том же приложении, это проблема на границах модулей из-за разных менеджеров памяти. В целом, это не рекомендуется.

+0

* Это не проблема в том же приложении *. Это проблема даже в том же приложении, потому что гораздо сложнее вручную отслеживать время жизни, чем позволить компилятору сделать это. –

+0

Я имел в виду, что это не проблема с разными менеджерами памяти. Бремя для пользователя более или менее одинаковое. –

+0

Вы не можете передавать эту запись через модули с разными менеджерами памяти в любом случае. Это управляемый тип. Так что часть вашего ответа в любом случае несколько спорна. Все, что в стороне, вы совершенно правы, указатель здесь действительно плохая идея. –

Смежные вопросы