Как передать "буквальные" целые числа по ссылке в C++ (новичок)

Редактировать: Как отмечали многие люди, передача по ссылке обычно не подходит для оптимизации примитивных типов. Это прекрасно, так что спасибо всем! Тем не менее, мой вопрос был действительно больше о том, почему буквальные значения не могут передаваться по ссылке, на которую был принят принятый ответ. Ура!


(Прости мою наивность: я довольно новичок в C++.)

Чтобы избежать неэффективности копирования по значению при вызове функции (скажем, "fillRect"), я хочу передать параметры по ссылке.

Если я поставлю параметры как объявленные локальные переменные, это будет работать нормально. Но если я предоставлю целые числа как "буквальные", я получу ошибку компиляции (без соответствующей функции).

void fillRect( int &x, int &y, int &width, int &height )
{
    // do something
}

int x=10, y=20, w=100, h=80;

fillRect(x, y, w, h); // this compiles and works!
fillRect(x, y, 100, 80); // but this doesn't compile ... why?

Что дает?

5 ответов

Решение

Вы не можете привязать литерал к lvalue-ссылке на non-const (потому что изменение значения литерала не имеет смысла). Однако вы можете привязать литерал к ссылке на const.

Так что это скомпилируется, если вы объявите fillRect как:

void fillRect(int const& x, int const& y, int const& width, int const& height)

В этом случае вы проходите ints. intОни настолько дешевы, что их копирование по ссылке, вероятно, ухудшит производительность вашей программы.

Функция fillRect вероятно, настолько дорого, что стоимость передачи его аргументов в любом случае не имеет значения. Или, может быть, это будет встроено, и передача аргументов будет бесплатной. Эти виды микрооптимизаций обычно вообще не являются оптимизациями и всегда должны руководствоваться результатами профилирования (если они вообще выполняются).

Чтобы избежать неэффективности копирования по значению при вызове функции

Остановись прямо там.

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

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

Вы должны передавать базовые типы только по ссылке, если вы собираетесь их изменять.

Передача по ссылке на самом деле медленнее для таких малых значений. Чтобы передать по ссылке, это скрытая передача указателя (в любом случае это значение типа int). Затем существует скрытая дополнительная косвенная указатель, которая не является бесплатной. Более просто передать значение.

Сделай это:

void fillRect( int x, int y, int width, int height )
{
    // do something
}

Компилятор, скорее всего, все равно будет встроен в вашу функцию, если только он не большой. Таким образом, вы не смогли бы улучшить производительность, будучи "умными" в том, как вы объявили функцию.

Во-первых, вы должны принять во внимание совет другого человека, чтобы он предпочитал передавать значения по простым типам. C (и расширение C++) были разработаны с учетом этого варианта использования, и именно для этого они оптимизированы.

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

Кажется, вы уже знакомы с проблемами копирования постоимости, поэтому вы устранили копирование постоимости. А теперь ты запутался, что передача необработанных значений не удалась?

Теперь я потерялся.

Другие вопросы по тегам