Есть ли прирост производительности при создании новой переменной, переданной по ссылке, по сравнению со значением? - PullRequest
0 голосов
/ 29 мая 2011

Меня не интересуют конкретные ценности, а только теоретические ответы.

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

  2. А как насчет объектов?Предполагая, что наш объект содержит некоторые значения для этого конкретного экземпляра объекта.Вместо того, чтобы создавать новый объект, можем ли мы передать его по ссылке для повышения производительности?Или мы должны clone это?

Надеюсь, я дал понять, заранее спасибо.

Ответы [ 5 ]

3 голосов
/ 29 мая 2011

Общее правило на современных процессорах: «математика - это быстро, память - медленно».

Если вы говорите о C ++, передавая целые числа, числа с плавающей запятой и даже небольшие объекты по значению скорее всего будет быстрее.Передача по ссылке может предотвратить различные оптимизации компилятора благодаря псевдонимам.

Для более крупных объектов передача по ссылке будет быстрее.(Определенно, не клонируйте их, потому что память медленная.)

Реальный ответ на этот вопрос, тем не менее, состоит в том, чтобы написать свой код естественным и простым способом, и не беспокойтесь о подобных вопросах, покаваш профилировщик говорит вам:

[обновить, чтобы уточнить проблему алиасинга]

Например, рассмотрим следующие две функции:

void
foo1(int a, int b, int &c, int &d)
{
    c = a + b;
    d = a - b;
}

void
foo2(const int &a, const int &b, int &c, int &d)
{
    c = a + b;
    d = a - b;
}

С включенной оптимизацией,мой компилятор (gcc 4.5.2, x86_64) производит этот код для foo1:

leal    (%rsi,%rdi), %eax
subl    %esi, %edi
movl    %eax, (%rdx)
movl    %edi, (%rcx)
ret

... и это для foo2:

movl    (%rsi), %eax
addl    (%rdi), %eax
movl    %eax, (%rdx)
movl    (%rdi), %eax
subl    (%rsi), %eax
movl    %eax, (%rcx)
ret

Ваш компилятор сделает что-то подобное.Проблема в том, что в foo2 «c» или «d» могут ссылаться на ту же область памяти, что и «a» или «b», поэтому компилятор должен вставить дополнительные загрузки / хранилища, чтобы беспокоиться об этом случае.

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

1 голос
/ 29 мая 2011

Это зависит от языка и реализации.Как правило, передача по ссылке происходит быстрее, потому что все, что вам нужно передать - это адрес (указатель).Для типов данных, меньших, чем указатель, может иметь небольшую экономию памяти и / или времени для передачи значения.Однако в большинстве языков для копирования даже небольшой объект потребует вызова конструктора копирования какого-либо вида, что убьет любую возможную экономию.С другой стороны, передача по ссылке создает псевдоним объекта или переменной, что в некоторых языках может быть проблемой.Кроме того, в некоторых языках вы не можете передать константу времени компиляции по ссылке;компилятор превращает вызов func(1) во что-то вроде int _1 = 1; func(_1).

. Следует также отметить, что в некоторых языках (например, в Java) невозможно передать объект по значению или примитивный тип по ссылке.Для этих языков, конечно, ваш вопрос спорный.

1 голос
/ 29 мая 2011

Если все, что вас интересует, это производительность, то, как правило, передача по ссылке работает лучше, чем передача по значению.

1 голос
/ 29 мая 2011

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

Для большого нетривиального объекта передача по значению будет намного дороже - вы создаете новую копию этого объекта.О цикле - PBV / PBR будут иметь значение только во время вызовов функций.

1 голос
/ 29 мая 2011

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

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