Способы передачи параметров функциям
Механизм параметров является основным способом обмена информацией между вызываемой и вызывающей функциями. В операторе вызова функции записывают аргументы функции, а в заголовке описания функции перечисляют параметры.
В С++ передача параметров осуществляется тремя способами:
· по копии (или по значению);
· по адресу (или через указатель);
Это определяется видом объявления параметра в заголовке функции.
Рассмотрим все три способа передачи на примере функции обмена Change(). Ей передаются два параметра, и она должна поменять местами их значения.
1. Передача по копии (по значению):
При передаче по значению объявление параметра похоже на объявление переменной: Тип ИмяПараметра. Такой параметр считается отдельной локальной переменной в теле функции. Ни в заголовке, ни в теле функции не должно быть других параметров или переменных с таким же именем.
Опишем работу программы. В области видимости функции main() существуют две локальные переменные A и B, которые проинициализированы значениями 10 и 20. В момент вызова функции Change() в стеке создаются параметры X и Y, которые получают копии значений аргументов A и B, а также переменная temp. Затем с помощью этой переменной происходит перестановка значений параметров X и Y (прежние значения выделены красным цветом). Однако по окончании работы функции Change() переменные X, Y и temp уничтожаются, поскольку являются локальными переменными, а значения аргументов A и B остаются неизменными.
Таким образом, функция Change() не решает поставленной перед ней задачи. Тем не менее, данный пример иллюстрирует особенность использования параметров-копий: никакие изменения значения параметра внутри функции не отражаются на значении переменной-аргумента, так как параметр является локальной переменной. Это способ передачи параметров в C++ используется по умолчанию.
2. Передача по адресу (через указатель):
Способ передачи параметров по адресу используется для того, чтобы через указатели обеспечить непосредственный доступ к значениям аргументов. В момент вызова функции Change() в стеке создаются параметры-указатели X и Y, которые получают копии адресов аргументов A и B. Теперь параметры X и Y указывают на аргументы A и B. Несмотря на то, что функции Change() не известны имена аргументов A и B, ей известны их адреса, поэтому она имеет доступ к их значениям. С помощью переменной temp происходит перестановка значений аргументов A и B (прежние значения выделены красным цветом). По окончании работы функции Change() переменные X, Y и temp уничтожаются, поскольку являются локальными переменными, но аргументы A и B остаются с новыми значениями. Таким образом, функция выполнила поставленную задачу.
3. Передача по ссылке:
Этот способ передачи параметров появился в C++ для того, чтобы упростить работу с указателями. При передаче по ссылке объявление параметра представляет собой объявление ссылки без инициализации: Тип &ИмяПараметра. Параметр-ссылка локальна в функции: ни в заголовке, ни в ее теле не должно быть объявлено других параметров и переменных с таким же именем. Инициализация параметра-ссылки выполняется во время вызова функции.
В самом простом случае при вызове функции в качестве аргумента задается имя переменной. Тип переменной-аргумента должен совпадать с типом параметра-ссылки. Ссылка становится альтернативным именем аргумента, поэтому любые действия, выполняемые со ссылкой в теле функции, мгновенно отражаются на состоянии аргумента.
В момент вызова функции Change() у аргументов A и B появляются вторые имена X и Y. Поэтому функция Change фактически напрямую работает с исходными переменными A и B и изменяет их.
Использование параметров-ссылок вместо передачи по значению или по адресу более эффективно, поскольку:
1) не требуется памяти для копирования аргументов в локальные переменные;
2) не требуется времени на их создание и уничтожение.
Поэтому программы с параметрами-ссылками работают быстрее и используют меньше памяти. Это имеет значение при передаче структур данных большого объема.
Передача параметра по ссылке также используется, если функция должна возвратить не один результат, а несколько.
Если требуется запретить изменение параметра, передаваемого по адресу или по ссылке, то используется модификатор const, например:
int Func( int a, const double &b);
СОВЕТ Рекомендуется указывать const перед всеми параметрами, изменение которых в функции не предусмотрено. Это облегчает отладку. Кроме того, на место параметра типа const& может передаваться константа.
Параметры, передаваемые в функцию, могут быть любого типа (например, вещественного, структурой, перечислением, объединением, указателем), кроме массива или функции, которые передаются с помощью указателей.
Источник
Способы передачи данных функции
В языке С++ данные в подпрограмму можно передавать тремя способами: по значению, по адресу и по ссылке. В языке С допустимы только два способа: по значению и по адресу.
Передача данных по значению
Этот способ передачи данных в подпрограмму является основным и действует по-умолчанию. Фактический параметр вычисляется в вызывающей функции и его значение передаётся на место формального параметра в вызываемой функции. На этом связь между фактическим и формальным параметрами прекращается.
В качестве фактического параметра можно использовать константу, переменную или более сложное выражение. Передача данных по значению пригодна только для простых данных, которые являются входными параметрами. Если параметр является выходным данным или массивом, то передача его в функцию по значению не приемлема.
Пример 1 . Вычислить сумму ряда с заданной точностью ε =10 -5 :
Для вычисления суммы ряда используем функцию. В неё передадим по значению x и eps . Результат вернём через имя функции оператором return .
Возможный вариант реализации программы:
using namespace std;
double fsum(double x, double eps);
double x, s, eps = 1.0e-5;
p = -p * t / (i * (i — 1));
Не сложно убедиться, что всё нормально работает. Но что делать, когда выходных параметров два или более? Через имя функции можно вернуть только один объект, остальные придётся возвращать через список. Позволит ли этот способ (передача по значению) вернуть через список параметров изменённые значения? Нет, не позволит. Давайте проверим это на несложном примере.
Пример 2 . Даны два числа, хранящиеся в переменных a и b . Используя подпрограмму, выполнить обмен содержимого ячеек этих переменных.
Данные передадим по значению. Они будут в этой задаче и входными, и выходными данными. Для контроля изменения содержимого ячеек памяти будем выводить на экран монитора промежуточные данные.
Возможный вариант реализации программы:
using namespace std;
void Obmen(double x, double y);
double a = 2.5, b = 3.1;
cout a и b после выхода из функции Obmen() .
Этот пример наглядно показывает, что через параметры, передаваемые по значению, нельзя вернуть результаты работы функции .
Передача данных по адресу
По адресу в функцию всегда передаются массивы (рассмотрим это в следующих темах). Для массива это вообще единственный способ передачи данных в языках С/С++. Так же по адресу можно передать те простые объекты, которые являются выходными данными (или входными и выходными одновременно).
В случае передачи данных по адресу фактический параметр может быть только переменной (константа или выражение не имеют адреса!).
Вернёмся к предыдущему примеру.
Пример 3 . Даны два числа, хранящиеся в переменных a и b . Используя подпрограмму, выполнить обмен содержимого ячеек этих переменных.
Данные передадим по адресу. Они будут в этой задаче и входными, и выходными данными. Для контроля изменения содержимого ячеек памяти будем выводить на экран монитора промежуточные данные.
Возможный вариант реализации программы:
using namespace std;
void Obmen(double *x, double *y);
double a = 2.5, b = 3.1;
cout main() ) вычисляются адреса объектов, передаваемых по адресу ( у нас — адреса переменных a и b . Пусть это будут числа 1000 и 1008 ), и затем эти адреса копируются в ячейки памяти — указатели, память под которые выделена в функции Obmen() (это x и y ). Зная адрес переменной, например, адрес переменной a , который теперь хранится в указателе x , можно, пользуясь операцией разыменование, не только прочитать, но и изменить значение исходной переменной.
Ни какой реальной передачи данных (в смысле копирования) из подпрограммы Obmen() назад в main() не делается. Мы на самом деле через указатели работаем с исходными объектами! Поэтому после выхода из функции Obmen() имеем изменённые переменные a и b (если быть точнее, переменные изменятся ещё до выхода из функции,то есть в момент перестановки в самой функции Obmen() ).
Передача данных по ссылке
Это ещё один из способов вернуть результат работы функции через список параметров. Напомним, что применяется только для С++. В языке С такого варианта нет.
При передаче данных по ссылке в функцию, куда передаются данные, создаются синонимы исходных объектов. Поэтому работа в подпрограмме ведётся именно с исходными объектами. Если в подпрограмме ссылочная переменная изменит значение, то это сразу отразится на исходной переменной.
В вызывающей функции параметр, передаваемый по ссылке, может быть только простой переменной любого известного типа.
Вернёмся снова к примеру обмена, только данные передадим по ссылке.
Пример 4 . Даны два числа, хранящиеся в переменных a и b . Используя подпрограмму, выполнить обмен содержимого ячеек этих переменных.
Возможный вариант реализации программы:
using namespace std;
double a = 2.5, b = 3.1;
cout & перед именем переменной (работаем с ссылкой на объект), а далее в теле подпрограммы используется просто имя этой переменной. При вызове в списке фактических параметров задаётся имя нужной переменной.
Для простых объектов передача данных по ссылке предпочтительнее, чем передача по адресу, так как в этом случае текст функции проще, легче читается, не требуется выполнять операции разыменования.
К недостатку способа (передача данных по ссылке) можно отнести то, что по вызову функции нельзя понять, что параметр передаётся именно по ссылке, а не по значению, и как следствие, этот параметр скорее всего изменяется функцией. Чтобы не было сомнений, всегда смотрите на запись прототипов функций, использованных в программе. Прототипы всегда доступны, даже если сами функции имеются только в виде объектных модулей.
Источник
C++. Функции. Передача параметров. Оператор return
Из данной статьи Вы узнаете о передаче параметров в функцию и о возврате результата с помощью оператора return. Рассмотрим теоретический материал.
Передача параметров в функцию
Обмен информацией между вызываемой и вызывающей функциями осуществляется с помощью механизма передачи параметров. Список_переменных, указанный в заголовке функции называется формальными параметрами или просто параметрами функции. Список_переменных в операторе вызова функции — это фактические параметры или аргументы.
Передача параметров выполняется следующим образом. Вычисляются выражения, стоящие на месте фактических параметров. Затем формальным параметрам присваиваются значения фактических. Выполняется проверка типов и при необходимости выполняется их преобразование.
Передача параметров в функцию может осуществляться по значению и по адресу.
При передачи данных по значению функция работает с копиями фактических параметров, и доступна к исходным значениям аргументов у нее нет. При передачи по адресу в функцию передается не переменная, а ее адрес, и, следовательно, функция имеет доступ к ячейкам памяти, в которых хранятся аргументов. Таким образом, данные, переданные по значению, функция изменить не может, в отличие от данных, переданных по адресу.
Если требуется запретить изменение параметра внутри функции, используют модификатор const. Заголовок функции в общем виде будет выглядеть так:
Источник
Способы передачи данных в функцию
Данные в функции передаются по значению, адресу или ссылке.
При передачи по значению исходные данные из функции main заносятся в параметры функции. Функция производит действия над параметрами, а, следовательно, над копиями исходных данных, передаваемых из функции main. Следовательно, изнутри мы не можем изменить исходные данные. Обратной связи нет.
Передача данных по адресу.
Адрес – уникальная и однозначная характеристика данного. Зная адрес данного, можно извлечь данное по адресу или изменить данное по адресу. В функцию через параметр мы можем передать адрес данного, объявленного в функции main. Внутри функции мы можем извлечь данное по адресу или изменить данное по адресу. Этот механизм используется для передачи из функции результатов, если их больше чем один.
Данное, переданное по адресу, можно использовать внутри функции и изменять.
Вывод: Данное, переданное по значению, оказывается защищенным от изменений внутри функции. Если данные не должны быть изменены, они должны передаваться по значению. Если данные хотим изменить внутри функции, они передаются по адресу (например, передача двух и более результатов из функции).
Механизм передачи второго, третьего ……. Результата из функции.
Пусть из функции необходимо предать через параметры результат целого типа.
Объявить в функции main переменную целого типа под результат.
В функции main в операторе вызова этой функции в качестве соответствующего аргумента передать адрес объявленной переменной.
В имени функции и в прототипе объявить параметр указатель на целый тип.
Внутри функции вычислить результат и записать его значение по указанному в параметре адресу.
То же самое схематично:
Int res; //переменная целого типа под результат.
… func (…, & res); // передали в функцию адрес переменной res.
Printf (“res=%d\n”, res); //вывели полученный из функции результат
Int res; //объявили переменную под результат
Res=…; //вычислили результат
*p=res; // возвратили результат функции через параметр
Передавая адрес аргумента мы открываем из функции прямой доступ к аргументу, экономя при этом память.
Запретить изменение аргумента, при передаче адреса можно, для этого надо объявить параметр const int *p;
Передача аргумента по ссылке
Ссылка – псевдоним какого-либо данного. При объявлении ссылки она обязательно инициализируется именем другого объекта (адресата) и с этого момента становится альтернативным именем адресата. Все что делается со ссылкой, происходит и с самим объектом. Ссылку нельзя переназначать. Ссылка только ссылается на один объект.
При передаче по ссылке экономится память и есть прямой доступ к аргументу. При необходимости аргумент можно защитить от изменения:
Написать программу с функцией вычисляющей корни квадратного уравнения
Анализ характеристик функции
1. Название функции: kvadr
2. Исходные данные (коэффициенты double a,b,c)
3. Результаты (через return передаем результат типа bool(который true-false))
корень x1: double &x1;
bool kdvadr(double a, double b, double c, double &x1, double &x2)
Источник