Передача параметров в функции в C++ для начинающих

Сайт не является учебником по программированию. Это только небольшой авторский сборник информации в помощь начинающим программистам.

   Передача параметров в функции в C++ для начинающих крайне важная информация. Я стараюсь не собирать всё в кучу, поэтому в этой статье будет выложен материал по теме только частично.

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

Код C++ Передача параметров в функции Обычный, Ссылка, Указатель

При первом обращении в функцию передается параметр, равный value. Внутри функции этот параметр как эстафетную палочку принимает переменная x и вся обработка идет с этим x, а сама переменная value тихо отходит курить в сторонку «Вдруг пригожусь» При этом переменная x является локальной переменной, т.к. объявлена внутри функции, а значит всё что происходит с ней, всё происходит только в пределах этой функции. При попытке вывести на экран value value снова играет главную роль, но она же просто курила в сторонке и никто ее не трогал. Как было ей присвоено 10, так и осталось

При втором обращении в качестве параметра передается ссылка. Так обращение к ссылке точно такое же как обращение к переменной, то такой вызов совершенно такой же как и первый, НО сама работа программы при таком вызове происходит по другому. Так как функция принимает параметр в качестве ссылки, то получается что-то типа Ссылка говорит объекту: «Тебе надо, ты и делай». Т.е. выходит так, что в отличие от первого варианта, объект только собрался курить в сторонке, а ссылка ему сразу пинком под зад: «Я курить, а если ничего не сделаем звездюлей тебе вешать будут». В общем получается, что value теперь как входной, так и выходной параметр. При попытке вывода на экран выведется 11, потому что обрабатываться будет сам параметр, а не ссылка на него

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

Что я еще могу сказать. Первый вариант можно привести ко второму или третьему, если например, объявить глобальную переменную (int z), после этого внутри функции присвоить в нее полученную x, а после вызова функции из тела программы написать value=z., а оно надо? можно еще написать value=sum_value(value) , но удобнее использовать ссылки

  • —>  Передача обычного параметра в функцию = входной параметр
    —>  Передача в функцию ссылки/указателя = как входной, так и выходной параметр

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

  •     Я бы говорил так: основное назначение ссылки упростить изменение параметра передаваемого в функцию, изменяя принимаемый параметр вне функции, но обрабатывая его внутри неё.

Меня достаточно долго интересовал вопрос почему во многих книгах в функции передаются параметры как константные ссылки, да еще и разные опытные программисты бесятся если неопытные программисты используют ссылки как параметры для функций и не объявляют их константными. Вы можете часто слышать один и тот же довод: «Вы так убережете себя от своих же собственных ошибок». Сначала мне такие константные ссылки очень мешали читать код и значит понимать о чем речь, да и никак понять не мог от каких-же это моих же ошибок это должно меня спасать.
   При передаче обычного параметра вовнутрь функции, внутри этой функции создается локальная копия такого параметра и в программе получаются две независимые друг от друга переменные. Само по себе копирование предполагает некоторые затраты времени и если копируется небольшой объект, то эти затраты вряд ли заметны, но со временем вам может потребоваться обрабатывать объекты приличных размеров, что существенно увеличит время выполнения. Чтобы избежать больших затрат времени как раз и используют ссылки как параметры, принимаемые функцией.
   Если программист в качестве параметра функции указывает ссылку на объект, то он скорее всего или преднамеренно хочет изменять объект как глобальный или же хочет работать с этим объектом, но предполагает сам этот объект не трогать. Как вы должны были понять, использование обычных параметров увеличивают время выполнения программы из-за того, что эти параметры копируются. Использование ссылок помогает оптимизировать программу и снизить затраты времени. Вот тут такой момент, что если вы не планируете изменять сам объект, который передаете туда в функцию, но хотите немного оптимизировать код, то пишите в функцию не просто ссылку, а константную.
 

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

Вы пишите, например такой код

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

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

Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

18 комментариев: Передача параметров в функции в C++ для начинающих

  • Anonymous говорит:

    "Первый вариант можно привести ко второму или третьему, если например, объявить глобальную переменную (int z), после этого внутри функции присвоить в нее полученную x, а после вызова функции из тела программы написать value=x"Наверно, надо написать value=z, так как через глобальную переменную z в данном случае передаётся выходная информация функции.

  • bazikmaloj говорит:

    а как написать функцию по вычисление целых чисел умножение! в языке С#

  • Аноним говорит:

    Все разжовано, и досупно. огромное спасибо. Где можно найти сборник ваших статей?

    Автор сайта отвечает:
    Пожалуйста)
    Про сборник статей не понял чего-то. Если это вопрос про содержание списка тем сайта, то главная страница. Сайт ci-plus-plus-snachala.ru

  • Аноним говорит:

    автор спасибо большое за статью, но учите орфографию и пишите чуть короче. успехов )

    Автор сайта отвечает:
    писать короче — означает убрать какие-то моменты. Гораздо больше людей нуждаются в таком стиле изложения материалов, где пусть будет больше описано, но чтобы понятно стало, чем в стиле, где пусть будет кратко и только то, что нужно. Это все-таки не справочник для умеющих, а сайт для начинающих.
    А по поводу орфографии вы не правы. Что мне и стоило бы учить, так это правила пунктуации. Слова я пишу достаточно грамотно, а знаки препинания расставляю не так, как должно быть. Пунктуация — знаки препинания. Орфография — правильное написание слов.

  • Аноним говорит:

    Здравствуйте, помогите, пожалуйста с заданием, никак не могу вникнуть в суть -_-
    Написать программу, вычисляющую сумму всех положительных чисел, введённых с клавиатуры, и номер первого положительного числа.
    Например, при вводе с клавиатуры чисел: -1, -2, -3, 0, 0, 0, 1, 2, 3 сумма равна 6, номер первого положительного равен 7.
    Функция main: 1. вызывает функцию inout; 2. выводит запрос на продолжение работы и в соответствии с ответом пользователя производит дальнейшие действия.
    Функция inout: 1. объявляет переменную int i; 2. передаёт переменную i по указателю функции func; 3. выводит на экран результат работы.
    Функция func: 1. получает указатель на переменную i; 2. запрашивает и i получает неопределённое количество чисел, вводящихся с клавиатуры; 3. переменной присваивается номер первого положительного элемента; 4. вычисляет сумму положительных элементов и возвращает вычисленную сумму.

    Автор сайта отвечает:

  • Wao-Bao говорит:

    Е-мое!!! Можно же просто и толково объяснить. После кучи статей наконец понял механизм передачи параметров.

    Спасибо автору.  Все по делу, никакой воды и пустых малопонятных слов. Можно использовать как образец для учебного пособия.

    (как прототип :)))))))    Спасибо !

  • Harrix говорит:

    В функции srav допущена ошибка. Там при сравнении используется один знак равно, а не два, как нужно.

    • admin говорит:

      Если вы читали тему, то должны были понять, что это специально так написано.
      Над примерами с ошибкой идет описание.

  • Shurkec говорит:

    Проясните, пожалуйста, ситуацию с передачей массивов (возможно я что-то пропустил или не понял). Возможно ли передать в функция массив как обычный параметр, чтобы его значения менялись только в функции. Я, к примеру, делаю так:

    Эту функцию вызываю так (ввод/вывод значений массива я опустил):

    Так вот — после вызова этой функции значения массива mat меняются, а мне этого к примеру не нужно. Или значения массивов передаются именно как ссылки?

     

    • admin говорит:

      Массив из функции вернуть нельзя.
      При передаче массива в функцию, имя массива неявно приводится к указателю на первый элемент этого массива. Так как получается эффект получения параметра по указателю, то копии массива не делается. Поэтому все изменения внутри функции действуют и на него. Варианты решения: использовать обьект класса или структуры, использовать вектор, использовать обьект array(c++11), или руками делать внутри функции новый массив и копироаать в него данные для следующей обработки.

  • Vitek Beluy говорит:

    а можно теперь как-то сделать к этому счетчик количества вызова функций?

    • admin говорит:

      Можно
      Глобальной переменной
      Статической переменной
      Передачей параметра по ссылке
      Передачей указателя на массив
      Сохранением в файл
      Другими способами…

  • Валерий говорит:

    меня интересует иное. Как функция знает соответствие входных переменных  внутренним переменным в её теле.

    • admin говорит:

      Мы сами ей говорим в момент её вызова, что мы в ней извне использовать станем. У неё два варианта: использовать извне что-то напрямую или использовать извне не напрямую. Это мы говорим сами, говорим, когда внутри функции выбираем, как будем использовать параметры (по ссылке или нет). В общем, сама она знает ровно столько, сколько мы ей сказали знать.

      Не очень понял вопрос, но надеюсь ответ получился понятным.
      1. Место вызова функции.
      2. Параметры функции.

  • Николай говорит:

    Скажите пожалуйста, что с ней не так???

    Почему компилятор выдает мне это?

    C:\Users\USER\Desktop\Hashtag_Zvukooperator\exam\main.c:8:38: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
    void func(int arr[], int num, double &sp, double &so)

    • admin говорит:

      Без понятия. Если компилятор C++, должно работать.

      • Дима говорит:

        Какой из способов передачи параметров расходует больше памяти?

        • admin говорит:

          Если в функцию отдаётся маленький объект (double, int, char…), то одинаково быстро.
          Если в функцию отдаётся большой объект (класс, структура), то по указателю и ссылке одинаково быстрее, чем по значению.

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     

Яндекс.Метрика

НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

Демотиватор эфолюция человека

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок