Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет89/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   85   86   87   88   89   90   91   92   ...   256
4.6.3 Передача параметров 
При вызове функции выделяется память для ее формальных параметров, и каждый формальный 
параметр инициализируется значением соответствующего фактического параметра. Семантика 
передачи параметров тождественна семантике инициализации. В частности, сверяются типы 
формального и соответствующего ему фактического параметра, и выполняются все стандартные и 
пользовательские преобразования типа. Существуют специальные правила передачи массивов 
($$4.6.5). Есть возможность передать параметр, минуя контроль типа ($$4.6.8), и возможность задать 


Бьерн Страуструп.
Язык программирования С++ 
 
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); // ошибка: здесь нужно преобразовывать тип 



Достарыңызбен бөлісу:
1   ...   85   86   87   88   89   90   91   92   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет