Бьерн Страуструп.
Язык программирования С++
108
стандартное значение параметра ($$4.6.7). Рассмотрим функцию:
void f(int val, int& ref)
{
val++;
ref++;
}
При вызове f() в выражении val++ увеличивается локальная копия
первого фактического параметра,
тогда как в ref++ - сам второй фактический параметр увеличивается сам. Поэтому в функции
void g()
{
int i = 1;
int j = 1;
f(i,j);
}
увеличится значение j, но не i. Первый параметр i передается по значению, а второй параметр j
передается по ссылке. В $$2.3.10 мы говорили, что функции, которые изменяют свой передаваемый по
ссылке параметр, труднее понять, и что поэтому лучше их избегать (см. также $$10.2.2). Но большие
объекты, очевидно, гораздо эффективнее передавать по ссылке, чем по значению.
Правда можно
описать параметр со спецификацией const, чтобы гарантировать, что передача по ссылке используется
только для эффективности, и вызываемая функция не может изменить значение объекта:
void f(const large& arg)
{
// значение "arg" нельзя изменить без явных
// операций преобразования типа
}
Если в описании параметра ссылки const не указано, то это рассматривается как намерение изменять
передаваемый объект:
void g(large& arg); // считается, что в g() arg будет меняться
Отсюда мораль: используйте const всюду, где возможно.
Точно так же, описание параметра, являющегося указателем, со спецификацией const говорит о том,
что указуемый объект не будет изменяться в вызываемой функции. Например:
extern int strlen(const char*); //
из
extern char* strcpy(char* to, const char* from);
extern int strcmp(const char*, const char*);
Значение такого приема растет вместе с ростом программы.
Отметим, что семантика передачи параметров отличается от семантики присваивания. Это различие
существенно для параметров, являющихся const или ссылкой, а также для параметров с типом,
определенным пользователем ($1.4.2).
Литерал, константу и параметр, требующий преобразования, можно передавать как параметр типа
const&, но без спецификации const передавать нельзя. Допуская преобразования для параметра типа
const T&, мы гарантируем, что он может принимать значения из того же множества, что и параметр типа
T, значение которого передается при необходимости с помощью временной переменной.
float fsqrt(const float&);
// функция sqrt в стиле Фортрана
void g(double d)
{
float
r;
r = fsqrt(2.0f);
// передача ссылки на временную
// переменную, содержащую 2.0f
r = fsqrt(r);
// передача ссылки на r
r = fsqrt(d);
// передача ссылки на временную
// переменную, содержащую float(d)
Бьерн Страуструп.
Язык программирования С++
109
}
Запрет на преобразования типа для параметров-ссылок без спецификации const введен для того, чтобы
избежать нелепых ошибок, связанных с использованием при передаче параметров временных
переменных:
void update(float& i);
void g(double d)
{
float
r;
update(2.0f); // ошибка: параметр-константа
update(r); // нормально: передается ссылка на r
update(d); // ошибка: здесь нужно преобразовывать тип
}
Достарыңызбен бөлісу: