2015-05-02 1 views
6

Рассмотрим следующую функцию:Проходя постоянные ссылки примитивных типов в качестве аргументов функции

template <class T, class Priority> 
void MutableQueue<T, Priority>::update(const T& item, const Priority& priority) 
{ 
    ... 
} 

бы составителям современные x86-64 быть достаточно умна, чтобы передать приоритет аргумент по значению, а не ссылки, если тип приоритета может поместиться в регистр?

+1

Я подозреваю, что да. Однако, если реализация подвергается воздействию внешних модулей, она должна соответствовать требованиям ABI - в этом случае ссылка является ссылкой. В общем, вы хотите избежать ссылок на примитивы - и есть способы сделать это. – davmac

+1

Я предполагаю, что если экземпляр типа 'T' может вписаться в регистр, компилятор будет проходить по копии. В противном случае он, вероятно, передаст переменную указателем. –

+1

Я сделал простой тест с компилятором clang. Кажется, что компилятор действительно делает оптимизацию. Он в основном генерирует оптимизированную версию (например, встраивание функции или передачу по значению) и версию (которая может быть не использована и просто находится там в коде), которая соответствует требованиям ABI. –

ответ

0

Это полностью зависит от платформы и компилятора, и поэтому аргументы передаются функции.
Эти особенности определены в ABI системы, в которой работает программа; некоторые из них имеют большое количество регистров и поэтому используют их в основном. Некоторые вставляют их все в стек. Некоторые смешивают их вместе с N-м параметром.

Опять же, на это нельзя положиться; вы можете проверить это несколькими способами. Язык C++ не имеет понятия о регистре.

2

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

Чтобы ответить на ваш вопрос

бы составители современные x86-64 быть достаточно умны, чтобы передать аргумент приоритета по значению, а не ссылку, если тип приоритета может вписываться в регистр?

Я просто попробую. См для себя:

Это код:

template<typename T> 
T square(const T& num) { 
    return num * num; 
} 

int sq(int x) { 
    return square(x); 
} 

GCC -O3, -O2 и -O1 надежно выполнить это оптимизация.

Clang 3.5.1, с другой стороны, похоже, не выполняет эту оптимизацию.

Должны ли вы считать на такую ​​оптимизацию? Не всегда, а не совсем - стандарт C++ ничего не говорит о том, когда такая оптимизация может произойти. На практике, если вы используете GCC, вы можете 'ожидать' оптимизации.

Если вы абсолютно уверены, что такая оптимизация произойдет, вы захотите использовать template specialization.

+1

Оптимизация, которая выполняет эту замену, кажется, '-fipa-sra'. Кажется, clang не поддерживает его. – dyp

+0

@ dyp: исправлено. – EyasSH

2

Компилятор может выполнять оптимизацию, но это необязательно.

Чтобы заставить пройти «лучший» тип, вы можете использовать импульс: http://www.boost.org/doc/libs/1_55_0/libs/utility/call_traits.htm

Замена const T& (где передача по значению является правильным) путем call_traits<T>::param_type.

Так что ваш код может стать:

template <class T, class Priority> 
void MutableQueue<T, Priority>::update(call_traits<T>::param_type item, 
             call_traits<Priority>::param_type priority) 
{ 
    ... 
} 
Смежные вопросы