Бьерн Страуструп - Язык программирования С++. Главы 2-4
Страница 60. Передача параметров


 

4.6.3 Передача параметров

 При вызове функции выделяется память для ее формальных параметров,
 и каждый формальный параметр инициализируется значением
 соответствующего фактического параметра. Семантика передачи
 параметров тождественна семантике инициализации. В частности, сверяются
 типы формального и соответствующего ему фактического параметра, и
 выполняются все стандартные и пользовательские преобразования типа.
 Существуют специальные правила передачи массивов ($$4.6.5).
 Есть возможность передать параметр, минуя контроль типа ($$4.6.8),
 и возможность задать стандартное значение параметра ($$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*);  // из <string.h>
           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)
        }

 Запрет на преобразования типа для параметров-ссылок без спецификации
 const введен для того, чтобы избежать нелепых ошибок, связанных
 с использованием при передаче параметров временных переменных:

       void update(float& i);

       void g(double d)
       {
         float r;

         update(2.0f);    // ошибка: параметр-константа
         update(r);       // нормально: передается ссылка на r
         update(d);       // ошибка: здесь нужно преобразовывать тип

      }

 
« Предыдущая статья   Следующая статья »