Каковы преимущества для передачи целочисленных типов по const ref - PullRequest
9 голосов
/ 13 ноября 2009

Вопрос: есть ли смысл передавать целочисленный тип по константной ссылке, а не просто по значению.

т.

void foo(const int& n); // case #1

против

void foo(int n); // case #2

Ответ ясен для пользовательских типов, случай № 1 позволяет избежать ненужного копирования при обеспечении константности объекта. Однако в приведенном выше случае, ссылка и целое число (по крайней мере, в моей системе) имеют одинаковый размер, поэтому я не могу представить, что есть много различий в том, сколько времени требуется для вызова функции (из-за копирование). Однако мой вопрос действительно связан с компилятором, включающим функцию:

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

Любой совет приветствуется.

Ответы [ 12 ]

12 голосов
/ 13 ноября 2009

Передача встроенного типа int с помощью const ref на самом деле будет незначительной де-оптимизацией (как правило). По крайней мере, для не встроенной функции. Компилятору, возможно, придется фактически передать указатель, который должен быть разыменован, чтобы получить значение. Вы можете подумать, что это всегда может оптимизировать это, но правила наложения имен и необходимость поддержки отдельной компиляции могут заставить руку компилятора.

Однако, для вашего второстепенного вопроса:

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

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

7 голосов
/ 13 ноября 2009

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

Я тестировал с gcc, и результаты были действительно такими же. вот код, который я тестировал:

inline int foo(const int& n) {
  return n * 2;
}

int bar(int x) {
  int y = foo(x);
  return y;
}

(с и без const & по параметру foo's n)

Затем я скомпилировал с помощью gcc 4.0.1 следующую командную строку:

g++ -O3 -S -o foo.s foo.cc

Выводы двух компиляций были идентичны.

6 голосов
/ 13 ноября 2009

Меня действительно раздражает, когда кто-то использует константные ссылки, подобные этим, для основных типов данных. Я не вижу никакой пользы от этого, хотя можно утверждать, что для типов данных больше sizeof(pointer) это может быть более эффективным. Хотя мне действительно безразличны такие мелкие «оптимизации».

4 голосов
/ 13 ноября 2009

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

2 голосов
/ 13 ноября 2009

Вы можете использовать boost::call_traits<your type>::param_type для оптимальной передачи параметров. По умолчанию используется простая передача параметров примитивных типов и передача по константной ссылке на структуры и классы.

2 голосов
/ 13 ноября 2009

Многие люди говорят, что между ними нет разницы. Я вижу один (возможно, надуманный) случай, в котором разница будет иметь значение ...

int i = 0;

void f(const int &j)
{
    i++;

    if (j == 0)
    {        
        // Do something.
    }
}

void g()
{
    f(i);
}

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

2 голосов
/ 13 ноября 2009

При написании или использовании шаблонов вы можете получить (const int &), потому что создатель шаблона не может знать, какой тип на самом деле. Если объект тяжеловесный, передача ссылки является правильным решением; если это int или что-то, компилятор может оптимизировать его.

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

1 голос
/ 13 ноября 2009

Не делай этого. int имеет тот же размер, что и указатель / ссылка на обычных 32-битных платформах, и меньше на 64-битных, поэтому вы можете получить преимущество в производительности вместо выгоды. Я имею в виду, что все аргументы функции помещаются в стек для того, чтобы функция могла их прочитать, и это будет либо ваш int, либо его адрес в случае ссылки. Другим недостатком является то, что вызываемый абонент будет либо обращаться к вашему n через косвенное обращение (разыменование адреса), либо копировать его в стек в качестве оптимизации.

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

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

1 голос
/ 13 ноября 2009

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

0 голосов
/ 13 ноября 2009

Пожалуйста, прочитайте Хотите скорость? Передайте по значению Дейв Абрахамс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...