Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

Сколько есть способов передачи аргументов в функцию?

#c #cpp


Как по мне, то в С есть передача аргументов в функцию только по значению, а в С++
по факту тоже только передача по значению. То есть, передачи по указателю не может
быть, потому что указатель содержит адрес, а это тоже значение. Так что правильней
говорить, что передача по значению. Ну а насчет ссылок, то это те же указатели с константным
адресом и которые неявно преобразуются к указателю, так что тоже передача по значению.
То есть, есть только передача по значению. А когда говорят о передаче по указателю
и ссылке, то это скорей для того, чтобы внести ясность о том, будет ли переменная копирована
или взят её адрес или так же неявно взят адрес с невозможностью заменить его на другой
адрес.

В общем, условно(для упрощения понимания) есть 2 способа передачи аргументов в функцию
в Си :
по значению,
по указателю. 
И 3 способа в C++:
по значению,
по указателю,
по ссылке.

А по факту везде передается по значению и только.
В тесте по Си были 2 ответа : по значению, и по указателю. Но вопрос там был другой
"Какими способами можно передавать параметры в функцию?". То есть, не аргументы, а
параметры. Не совсем понимаю этот момент, но если предположить, что аргументы передаются
в параметры, а потом параметры в тело функции, то параметры вполне могут передаваться
по значению или указателю или по ссылке( в C++). И будет выглядеть как - 
void func1 ( int   arg );
void func2 ( int * arg );
void func3 ( int & arg );

Из кода видно, что сами параметры могут быть и ссылкой и указателем, но тем не менее
во всех трех случаях инициализированы они будут аргументами, которые передаются только
по значению. 
Что-то мне кажется, что скорей всего не правильно был сформулирован вопрос теста
и параметры не передаются в функцию, так как они и так в её сигнатуре, а передаются
аргументы, ну а параметры просто инициализируются где-то между сигнатурой и телом в
области видимости под которую попадает тело функции.    


Ответы

Ответ 1



Насколько я понимаю, в C ровно один способ передачи аргументов: по значению. Передаёте ли вы по значению число или указатель, вы получаете с той стороны копию этого числа/указателя: если вы меняете число внутри функции, с его «внешним прообразом» (который может, кстати, быть и выражением) ничего не случается; если внешний прообраз меняется в течение выполнения функции, на значении аргумента это никак не отражается. Иногда говорят, что передавая указатель на объект в функцию, вы как бы тем самым неявно передаёте сам объект в функцию «по указателю». Это на самом деле не вполне верный подход. Давайте я приведу пример: представьте себе, что вам передали число. Вы использовали это число как индекс в глобальном массиве, и изменили элемент этого массива. Можно ли сказать, что вам был передан этот элемент? Нет, вы получили лишь число. Точно так же можно смотреть на указатель как на индекс в памяти, рассматриваемой как массив байт. Доступ к объекту через указатель ничем не лучше и не хуже доступа к ячейке массива по индексу. В C++ появился новый вид передачи параметров: по ссылке. По существу, передача «по ссылке» ничем не отличается от передачи указателя кроме того, что (1) ссылка не может соответствовать NULL-указателю в корректной программе, (2) ссылка синтаксически ведёт себя как разыменованный указатель. Однако, разработчики C++ советуют всё же видеть в передачу по ссылке другую семантику: ссылка является «алиасом», другими именем объекта. Хотя такая семантика и более привлекательна с точки зрения ясности программ, всё же ссылка на объект и сам объект — не одно и то же. В частности, ссылка может пережить объект, и вы получите при попытке обратиться к ней undefined behaviour. Если бы ссылка была самим объектом (как это часто пытаются подать), такого произойти бы не смогло. Следовать ли совету разработчиков или думать о передаче по ссылке как о синтаксическом сахаре для передачи по указателю — личное дело каждого. Я бы всё же советовал думать так, как советуют разработчики, но не упускать из виду, что эта абстракция «протекает». ЗЫ: Пример кода без явных ошибок (наподобие возврата ссылки на локальную переменную), в котором ссылка на объект переживает сам объект: class X { struct C { int x; }; C* pc; void f(int& x) { g(); cout << x << endl; } void g() { delete pc; } public: X() : pc(new C()) {} void run() { f(pc->x); } };

Ответ 2



при передачи по значению передаваемое значение не меняется, а внутри функции создается временная переменная. при передачи по указателю или ссылки передается только адрес, передаваемый объект можно изменить изнутри функции и не создается локальной (временной) переменной внутри функции. разница между передачи ссылкой и указателем в удобстве употребления (не надо писать звездочку каждый раз внутри функции). ниже пример: #include using namespace std; void f_value(int a){ // значение a = 10; // изменяем параметр } void f_poiner(int * a){ // указатель *a = 10; // изменяем параметр } void f_reference(int & a){ // ссылка a = 20; // изменяем параметр } int main(){ int a = 0; cout << "a = " << a << endl; f_value(a); // значение переменной (а) НЕ изменится после выполнения cout << "a = " << a << endl; f_poiner(&a); // значение переменной (а) изменится после выполнения cout << "a = " << a << endl; f_reference(a); // значение переменной (а) изменится после выполнения cout << "a = " << a << endl; return 0; } --------------------------------------------------- a = 0 a = 0 a = 10 a = 20 Press to close this window...

Ответ 3



пока читал вопрос несколько раз запустался :)) int foo(int a);//"a" это параметр функции int foo(int a){//между "){" произойдёт присвоение a="значение из аргумента" return a+10; } int main(){ int c=100,g; g=foo(c);// "c" это аргумент функции //тут выполнится такой порядок действий: //временная_переменная="то что возвращает foo" //очистка того что занимала foo //g=временная_переменная return 0; } вот тут пример с ссылками тык. Так что всё "передаётся по значению" но надо же как то отличать передачу указателя, ссылки и объекта, ведь если объект занимает 1гб то при передачи самого объекта копироваться будет 1гб (того нужно 2 гб), а при передачи через указатель\ссылку нужно будет только пару байт. Потому такие передачи и называют по разному... так что да "некорректно задан вопрос"!

Ответ 4



Есть два способа, причем мы рассматриваем C++, а не си и не ассеблер( где можно говорить через стек или через регистры ) Передача по значению, где значение объекта копируется в стек или адресс объекта копируется в стек.... По ссылке, где в теле функции просто непосредственно обращаются к объекту, например сегменту данных, где была определега глобальная переменная, которая передается по ссылке. То есть, тут подменить адрес переданного объекта по ссылке нельзя в отличии от от передачи по указателю. Это просто как алиас объекта.

Комментариев нет:

Отправить комментарий