2010-04-06 2 views
29

Из того, что я понимаю: при передаче по значению функция создает локальную копию переданного аргумента и использует это; когда функция заканчивается, она выходит за рамки. Когда вы передаете ссылку const, функция использует ссылку на переданный аргумент, который не может быть изменен. Однако я не понимаю, почему один выбирал один за другим, за исключением ситуации, когда аргумент должен быть изменен и возвращен. Если у вас есть функция void, в которой ничего не возвращается, зачем выбирать один за другим?Зачем передавать ссылку const вместо значения?

РЕДАКТИРОВАТЬ: Таким образом, в основном передача константой const позволяет избежать копирования объекта. Так в каких ситуациях копировать объект хорошо? Я имею в виду, почему бы не просто использовать константные ссылки все время, если он постоянно оптимизирует производительность?

+1

Возможный дубликат http://stackoverflow.com/questions/1567138/const-t-arg-vs-t-arg –

+0

Ссылки на gf статьи ссылаются на ваш второй вопрос. Короче: если вам нужна копия, то передайте ее. –

+0

@ Кирилл Ах, это ответ на мой вопрос. Я искал «pass by const reference», и он ничего не менял, поэтому я пропустил это. – Maulrus

ответ

39

Существует два основных соображения. Один из них - это расход копирования переданного объекта, а второй - предположения, которые компилятор может сделать, когда объект является локальным объектом.

E.g. В первом виде в теле f нельзя предположить, что a и b не ссылаются на один и тот же объект; поэтому значение a должно быть перечитано после любой записи до b, на всякий случай. Во второй форме a не может быть изменен посредством записи на b, так как он является локальным для функции, поэтому эти повторные чтения не нужны.

void f(const Obj& a, Obj& b) 
{ 
    // a and b could reference the same object 
} 

void f(Obj a, Obj& b) 
{ 
    // a is local, b cannot be a reference to a 
} 

E.g.: В первом примере компилятор может предположить, что значение локального объекта не изменяется при выполнении несвязанного вызова. Без информации о h компилятор может не знать, не изменяется ли объект, с которым эта функция ссылается (через ссылочный параметр), на h. Например, этот объект может быть частью глобального состояния, которое изменяется на h.

void g(const Obj& a) 
{ 
    // ... 
    h(); // the value of a might change 
    // ... 
} 

void g(Obj a) 
{ 
    // ... 
    h(); // the value of a is unlikely to change 
    // ... 
} 

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

Передача параметра на const Следует выбирать ссылку, где требуется семантика ссылок, или как улучшение производительности, только если стоимость потенциального сглаживания будет перевешиваться за счет копирования параметра.

+0

Время от времени, копирование ваших параметров также может дать вам местные преимущества. –

+1

В чем смысл 'const Obj & a', если ссылочные данные могут измениться? Почему даже «const» в первую очередь? –

4

Выполнение копии объекта может в некоторых случаях существенно повлиять на производительность. Рассмотрим функцию, аргумент которой будет std::vector<long>, и вы хотите передать вектор с 1 миллионом элементов. В этом случае вы захотите использовать константную ссылку для передачи по значению. В this SO question вы можете найти простые общие правила для своего вопроса.

2

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

2

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

2

Передача аргумента по значению имеет накладные расходы на копию объекта, передаваемого функции.

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

2

Из-за преимуществ, которые вы получите. Допустим, у вас большой объект (с точки зрения размера в байтах). Теперь, если вы передаете этот объект по значению функции, необходимо создать ненужную копию из этого, однако вы можете получить тот же эффект, передав ссылку const этому объекту без создания копии. Поскольку ссылка обычно хранится как указатель под капотами, стоимость передачи ссылки составляет всего sizeof(pointer).

18

Передача аргументов по значению и, таким образом, их копирование может быть дорогостоящим - ссылки на const избегают этого дорогостоящего шага, все еще обещая вызывающему, что объект не будет изменен.

Обычно основные типы (int, double, ...) передаются по значению, а типы классов передаются по ссылке const.

Однако может быть exceptions, где полезная стоимость для классов может быть выгодной.

2

Массив не может быть передан по значению, поэтому это подходящее время для использования указателя const.

Смежные вопросы