Как передать "буквальные" целые числа по ссылке в C ++ (новичок) - PullRequest
14 голосов
/ 09 октября 2011

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


(Простите за наивность: я довольно новичок в 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 ]

21 голосов
/ 09 октября 2011

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

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

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

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

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

19 голосов
/ 09 октября 2011

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

Стоп.

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

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

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

9 голосов
/ 09 октября 2011

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

Сделайте это:

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

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

4 голосов
/ 09 октября 2011

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

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

0 голосов
/ 09 октября 2011

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

Теперь я потерян.

...