Подтвердить что ты не робот

Передача целых чисел в виде постоянных ссылок и копирование

Это может быть глупый вопрос, но я замечаю, что в большом количестве API-интерфейсов множество сигнатур методов, которые принимают целочисленные параметры, которые не предназначены для изменения, выглядят следующим образом:

void method(int x);

а не:

void method(const int &x);

Мне кажется, что оба они будут работать точно так же. (EDIT: видимо, не в некоторых случаях, см. Ответ Р. Сэмюэля Клачко). В первом случае значение копируется и, следовательно, не может изменить оригинал. В последнем случае передается постоянная ссылка, поэтому оригинал не может быть изменен.

Я хочу знать, почему один за другим - это потому, что производительность в основном такая же или даже лучше с предыдущей? например передавая 16-битное значение или 32-битное значение, а не 32-разрядный или 64-разрядный адрес? Это была единственная логическая причина, о которой я мог думать, я просто хочу знать, правильно ли это, а если нет, то почему и когда вы предпочитаете int x над const int &x и/или наоборот. Спасибо.

4b9b3361

Ответ 1

Это не просто стоимость передачи указателя (что, в сущности, эта ссылка), но и удаление ссылок в тело вызываемого метода для получения базового значения.

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

Ответ 2

Мне кажется, что оба они будут работать точно так же.

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

static int global_value = 0;

int doit(int x)
{
    ++global_value;
    return x + 1;
}

int main()
{
    return doit(global_value);
}

Этот код будет вести себя по-разному в зависимости от того, есть ли у вас int doit(int) или int doit(const int &)

Ответ 3

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

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

Кроме того, при передаче по значению функция может изменять копию. При передаче по постоянной ссылке функция не может изменять переменную (она помечена как const).

Ответ 4

  • В зависимости от базового набора команд, целочисленный параметр может быть передан как регистр или в стек. Регистр определенно быстрее, чем доступ к памяти, который всегда требовался бы в случае const ref (учитывая ранние архитектуры без кэша)

  • Вы не можете передать int-литерал как const int &

  • Явные приведения типов позволяют вам использовать const int & в * (const int *), открывая возможность изменить значение пройденной ссылки

Ответ 5

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

Большинство людей, похоже, не любят pass-by-const-ref для встроенных модулей из-за этого (некоторые очень). Однако я думаю, что в некоторых случаях было бы предпочтительнее, если вы хотите, чтобы компилятор помог вам в обеспечении того, чтобы значение не случайно было изменено внутри функции. Это не большая вещь, но иногда это может помочь.