оптимизация — C ++: возврат по значению, против возврата по ссылке постоянного объекта?

Что лучше для скорости программы после оптимизации компилятора: возврат по значению или возврат по ссылке на постоянный объект?

/// Generate a 'foo' value directly as a return type.
template< typename T >
inline T gen_foo();

/// Get a 'foo' reference of a persistent object.
template< typename T >
inline T const& get_foo();

T будут примитивами, указателями, указателями на члены или небольшими, определенными пользователем, данными типа P.O, D.

Насколько мне известно, это передача по значению, но есть возможный случай для передачи по ссылке:

  • Передача по значению:

    • возвращая один T является меньшим объектом и быстро копируется в переменную вызывающего.
    • оптимизатор может использовать (N) RVO и copy-elision для удаления возвращаемых копий.
    • оптимизатор может встроить генерирующий код или сгенерированное значение в код вызывающего.
    • программе не нужно будет получать доступ к оперативной памяти, кешируется или нет.
  • пройти по ссылке:

    • Оптимизатор может полностью оценить постоянное значение и заменить его использование буквальным эквивалентом. То, происходит ли это, влияет на остальную часть анализа.
    • если постоянное значение полностью вычисляется и подставляется как литерал:
      • нет значения для возврата.
      • оптимизатор может легко вставить буквальное значение.
      • Программа не должна иметь доступ к оперативной памяти, кешируется или нет.
    • если постоянное значение не может быть полностью оценено и заменено:
      • возврат одной ссылки — это маленький объект, который быстро копируется в переменную вызывающего.
      • оптимизатор может использовать (N) RVO и copy-elision, чтобы избежать возврата копий.
      • оптимизатор не может встроить генерирующий код или сгенерированное значение в код вызывающего.
      • Программа должна иметь доступ к ОЗУ, хотя, скорее всего, это будет в L1 / L2 / etc. кэш.

Фон:

Я вынужден учитывать это, потому что на некоторых платформах некоторые исключения с плавающей запятой срабатывают, если я возвращаю по значению, но не при заполнении по параметру. (Это само собой разумеющееся; этот вопрос не обсуждается по этому вопросу.) Итак, API, который я хотел, и API, которые я вынужден рассмотреть, это:

/// Generate a 'foo' value directly as a return type.
template< typename T >
inline T gen_foo();

/// Fill in a 'foo' passed in by reference.
template< typename T >
inline void fill_foo( T& r_foo );

Поскольку я ненавижу API-интерфейс fill (поскольку он отделяет определение от инициализации, предотвращает создание временных файлов и т. Д.), Я могу вместо этого преобразовать его в версию с возвратом по ссылке, что-то вроде:

/// Forward-declare 'Initialized_Foo'.
template< typename T > struct Initialized_Foo;

/// Get a 'foo' reference; this returns a persistent reference to a static object.
template< typename T >
inline T const& get_foo()
{
#if 0
// BAD: This calls 'fill_foo' *every* time, and breaks const-correctness.
thread_local static const T foo;
fill_foo( const_cast< T& >( foo ) );
return foo;
#else
// GOOD: This calls 'fill_foo' only *once*, and honours const-correctness.
thread_local static const Initialized_Foo< T > initialized_foo;
return initialized_foo.data;
#endif
}

/// A 'foo' initializer to call 'fill_foo' at construction time.
template< typename T >
struct Initialized_Foo
{
T data;
Initialized_Foo()
{
fill_foo( data );
}
};

0

Решение

Задача ещё не решена.

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

Других решений пока нет …

По вопросам рекламы [email protected]