Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 1 из 1
  1. #1
    Аватар для Tracker1
    Проверенный

    Статус
    Оффлайн
    Регистрация
    30.07.2013
    Сообщений
    54
    Репутация:
    84 ±

    [Цикл уроков программиста] 10. Функции(часть 2)

    Передача массивов в функцию

    Передача массивов в функцию имеет небольшое отличие от передачи простой переменной. В прототипе функции необходимо указывать идентификатор:

    PHP код:
    int simple_function (int array[]);
    int simple_function (int array[]) { return 0;} 
    Обратите внимание, что рядом с идентификатором и в объявлении и в определении стоят скобочки.

    При вызове функции, в которую нужно передать массив, указывается только идентификатор массива (без квадратных скобок):

    PHP код:
    int a[] = { 01};
    simple_function(a); 

    Запомните, при вызове указывается только идентификатор, а при объявлении/определении ещё и скобки.
    Глобальные переменные

    Глобальные переменные - это переменные, которые определены за пределами любой функции:
    PHP код:
    int x 0// глобальная переменная

    int main () { код main }

    void simple_function ()
    {
      
    5;


    Здесь переменная x видна из любой функции программы, в том числе и из simple_function. Что значит: "функция видит переменную"? Это значит, что внутри функции можно обращаться к этой переменной.

    Глобальные переменные существуют с того момента как они встретились в коде и до конца программы. Т.е. если глобальную переменную объявить после какой-нибудь функции, то в этой функции данную переменную нельзя будет использовать:
    PHP код:
    int main () { код main }

    void simple_function ()
    {
      
    // компилятор выдаст ошибку, переменная ещё не объявлена
    }

    int x 5// объявление глобальной переменной

    int getX ()
    {
      return 
    x// getx видит переменную x

    Переменная x объявлена после функций main и simple_function, а значит, в этих функциях её не видно.
    Локальные переменные

    Локальные переменные объявлены внутри функций и видны только в них самих:
    PHP код:
    void f1 ()
    {
      
    int a// объявление переменной
      
    f2();
    }

    void f2 ()
    {
      
    3// ошибка, отсутствует объявление переменной

    У каждой функции есть своя область видимости. В область видимости функции входят все глобальные переменные и переменные объявленные в этой функции.

    Механизм передачи значений через аргументы и return предназначен как раз для локальных переменных:
    PHP код:
    int x// глобальная переменная

    void f1 ()
    {
      
    int a 5;
      
    int b 3;
      
    int t 1;
      
    5;
      
    int c f2(b,a);
    }

    int f2(int aint t)
    {
      
    int b 1;
      return 
    a+t+x;

    Обе функции видят переменную x, т.к. она глобальная.

    У каждой функции свои переменные a,b,t. У f1 a=5,b=3,t=1, а у f2 a=3,t=5,b=1. Несмотря на то, что у этих функций есть переменные с одинаковыми идентификаторами, это всё-таки совершенно разные переменные. Будьте бдительны!

    Переменной c будет присвоено значение 13.
    Статические локальные переменные

    Обычные локальные переменные, когда функция завершается, уничтожаются. И при каждом выполнении функции, они создаются заново:
    PHP код:
    void simple_function ()
    {
      
    int a 0;
      
    1;


    В данном примере, сколько бы раз не вызывалась функция, переменная a никогда не станет больше единицы.

    Статические переменные определяются только один раз - когда функция вызывается в первый раз. Когда функция заканчивает выполнение операторов, статические переменные остаются в памяти. Когда функция снова вызывается, она продолжает их использовать:
    PHP код:
    int simple_function()
    {
      static 
    int a 0;
      
    1;
      return 
    a;
    }

    int main ()
    {
      
    int a 0;
      
    simple_function();
      
    cout << a// 1
      
    simple_function();
      
    cout << a// 2
      
    simple_function();
      
    cout << a// 3
      
    return 0;

    Передача аргументов по значению (pass-by-value)

    Рассмотрим пример:
    PHP код:
    int simple_function(int); // прототип ф-ии

    int main()
    {
      
    int x 4// переменная x в вызывающем окружении
      
    int y;
      
    simple_function(x); // возвращаемое значение ф-ии присваивается переменной y
      
    cout << x// 4
      
    return 0;
    }

    int simple_function(int x// переменная x в функции
    {
      
    5;
      return 
    x;

    В main мы объявляем две переменные, одной присваиваем значение. Затем вызываем функцию и передаём ей переменную x. Управление передаётся функции и начинается выполнение тела ф-ии.

    Обратите внимание, что в заголовке и теле функции используется переменная x. Но это не та переменная, которая объявлена в вызывающем окружении.

    Когда после вызова функции мы выводим значение x, на экране появляется 4, а не 9.

    Дело в том, что когда происходит вызов функции, значение аргумента копируется и в теле функции используется скопированное значение.

    Запомните, две переменные: переменная-аргумент из вызывающего окружения и переменная-параметр функции - две совершенно разные переменные, хранящиеся в разных участках памяти. Если вы измените переменную в функции, то это не значит что изменится и переменная из вызывающего окружения.

    Вот этот механизм и называется передачей по значению (pass-by-value). Мы передаём не саму переменную, а её значение. При этом происходит создание ещё одной переменной того же типа и в неё помещается такое же значение.

    Тут вот на какой момент стоит обратить внимание: внутри функции мы не можем работать с внешними переменными (за исключением глобальных), они не видны из функции! Мы можем работать только со значениями тех, которые мы передали в функцию в виде аргументов.
    Передача аргументо по ссылке (pass-by-reference)

    Ссылка на переменную - это другое имя той же переменной. Т.е. это как псевдоним.

    Передача по ссылке (pass-by-reference) позволяет изменять значение переменной из внешнего окружения внутри функции.
    PHP код:
    int simple_function(int&);  // прототип ф-ии

    int main ()
    {
      
    int x 4;       // переменная x в вызывающем окружении
      
    int y;
      
    simple_function(x); // присваивание переменной y возвращаемого значения функции
      
    cout << x// 9
      
    return 0;
    }

    int simple_function(intz// переменная z в функции
    {
      
    5;
      return 
    z;

    Для передачи по ссылке, после имени типа в обьявлении и определении нужно поставить амперсанд. Больше никаких изменений делать не нужно. Я только изменил имя переменной внутри функции для наглядности.

    x и z - одна и та же переменная. При обращении к одной из этих переменных мы обращаемся к одному участку памяти. При передаче аргумента по ссылке не происходит копирования. Просто для участка памяти, где содержится значение, создаётся ещё одно имя - z. Поэтому после вызова функции, у переменной x - новое значение 9.

    Через оператор return можно вернуть только одно значение. Передача по ссылке нужна, когда необходимо вернуть несколько значений. Нужно просто передать необходимое количество аргументов и внутри функции произвести над ними необходимые операции. При этом можно вообще ничего не возвращать (использовать тип void). Посмотрите на пример для наглядности:
    PHP код:
    void simple_function (int&, int&, int&);

    int main ()
    {
      
    int a 0;
      
    int b 2;
      
    int c 7;
      
    simple_function (abc);
      
    cout << a// 1
      
    cout << b// 4
      
    cout << c// 10
      
    return 0;
    }

    void simple_function (intxintyintz)
    {
      
    1;
      
    2;
      
    3;

    Передача аргументов по указателю (pass-by-pointer)

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

    Массивы всегда передаются в функции через указатели:
    PHP код:
    void simple_function (int a[]); // прототип

    int array[5];
    simple_function(array); // передача массива в функцию 
    При передаче значения по указателю не происходит копирования значений. Отличие же от ссылки в том, что указатель - это не другое имя переменной, указатель - это адрес в памяти по которому можно найти значение переменной. Пока что не обращайте внимания на эти тонкости. Просто запомните, что при передаче массива в функцию, мы используем указатели. Имя массива - это и есть переменная-указатель, но если после идентификатора стоят квадратные скобки с индексом, то происходит обращение к конкретному элементу массива:

    PHP код:
    int array[5];

    = array; // указатель
    = array[0]; // не указатель 
    Перегруженные функции

    Очень часто возникает ситуация, когда несколько функций выполняют одинаковые действия, только над разными типами. В данном случае можно использовать перегруженные функции.

    Перегруженные функции - это функции с одним именем, но с разными типами аргументов:
    PHP код:
    int simple_function (float afloat b);
    int simple_function (int aint b);
    int simple_function (int a); 
    Здесь представлено три объявления перегруженной функции simple_function. Для каждого варианта функции, нужно написать своё определение.

    Перегруженные функции могут отличаться не только типами аргументов, но и их количевством (сравните 2-е и 3-е объявления).

    И ещё один важный момент: в перегруженных функциях учитываются только аргументы, возвращаемое значение не играет никакой роли. В следующем примере, компилятор выдаст ошибку:
    PHP код:
    int simple_function (int a);
    float simple_function (int a); 
    Константные аргументы функции

    Как мы уже знаем, при передаче аргумента по значению, мы не можем изменить переменную из вызывающего окружения. Если мы всё же хотим изменить значение этой переменной, то аргумент нужно передавать по ссылке. Но иногда возникает ситуация, когда нужно передать аргумент по ссылке и при этом запретить его изменять. Для этого можно воспользоваться константными аргументами функции. В списке аргументов объявления/определения нужно поставить ключевое слово const перед соответствующим аргументом:
    PHP код:
    int simple_function(const int&, int);

    int simple_function(const intaint b);
    {
      
    1// Компилятор выдаст ошибку! Нельзя изменять переменную a
      
    return 0;


    Теперь, для чего это нужно: в следующих уроках мы познакомимся с новыми типами данных. Эти типы данных в некоторых случаях могут занимать сотни байт (сравните со стандартным типом double - 8 байт). Если передавать эти аргументы в функцию по значению, то будет происходить копирование, а это значит замедление программы. Поэтому для большей эффективности мы будем передавать эти переменные по ссылкам. Ну а чтобы "случайно" не изменить их значения, будем пользоваться константными аргументами.
    Встраиваемые функции (inline functions)

    Вызов функции, передача в неё значений, возврат значения, эти операции занимают довольно много процессорного времени. Когда мы будем рассматривать более реальные примеры, у нас будут функции в один-два оператора (в основном - математические), которые нужно будет выполнять тысячи раз в секунду. Так как размер функции небольшой (несколько операторов), то время выполнения тела функции будет меньше чем процесс вызова/передачи аргументов/возврата значения. Чтобы сократить время работы программы, можно воспользоваться встроенными функциями.

    Перед объявлением/определением функции нужно добавить ключевое слово inline.

    При этом, во время компиляции все вызовы функции будут заменены непосредственно кодом функции. При этом программа будет выполняться быстрее, но займёт больше памяти (если функция вызывается много раз):
    PHP код:
    inline void simple_function()
    {
      
    // тело функции
    }

    int main ()
    {
      
    simple_function();
      
    simple_function();
      
    simple_function();
      return 
    0;


    Во время компиляции этот код превратится в следующий:
    PHP код:
    int main ()
    {
      
    // тело функции
      // тело функции
      // тело функции
      
    return 0;

    Компилятор решает делать функцию встраиваемой или нет, в зависимости от размера функции. Т.е. если вы пытаетесь сделать длинную функцию (в которой, например, сотня операторов) встраиваемой, то компилятор сочтёт её слишком большой, и будет её использовать как обычную.
    Библиотечные функции

    Практически с первого урока мы уже использовали функции:
    PHP код:
    _getch();
    setlocale(LC_CTYPE,"Russian"); 

    Эти функции называются библиотечными. Их объявления находятся в заголовочных файлах, которые мы включаем в наши исходники с помощью #include. Определения этих функций расположены в библиотечных файлах с расширением .lib. Заголовочные файлы расположены в папке studio\VC\include, а библиотечные в studio\VC\lib (studio - папка, куда вы установили Visual Studio C++ ). Посмотрите на содержимое заголовочных файлов: conio.h и iostream.

    На сегодня всё.
    Последний раз редактировалось bredvix; 25.02.2014 в 18:03.

  2. Пользователь сказал cпасибо:
    vovandolg (16.10.2016)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •