#cpp
Есть следующий код: #include "stdio.h" void ptr(int *ptr, int d) { *ptr = d; } void ref(int &ref, int d) { ref = d; } int main(void) { int digit = 154; int &a = digit; ref(a, 999); printf("%d - %d\n", digit, a); ptr(&a, 1000); printf("%d - %d\n", digit, a); return 0; } Интересует следующее: Есть такое понятие как передача по значению, работает ли это понятие когда мы передаем аргумент: как указатель, как ссылку?(Лучше объяснить как и почему) P.S Мне почему-то кажется что когда мы передаем аргумент как указатель то создается внутренняя переменная (локальная), а значит тратится память и так каждый раз при передаче указателю. С ссылкой пока не ясно.
Ответы
Ответ 1
По сути, все варианты - передача по значению. При f(T t) по значению передается объект t, для которого создается временная копия. Очевидно, что при передаче по указателю f(T* t) по значению передается указатель t, для которого создается временная копия. Памяти тратится ровно столько, сколько занимает указатель. При передаче по ссылке f(T&t) фактически происходит передача указателя. Можно рассматривать эту передачу как передачу по указателю, просто указатель в теле функции везде разыменован, так что не приходится писать то-то типа *t = 5; - грубо говоря, эту * за вас добавляет компилятор. Соответственно, памяти и в этом случае тратится ровно столько, сколько занимает указатель. Как иллюстрация - https://godbolt.org/g/TSZt1yОтвет 2
Если у вас есть функция, объявленная, к примеру, как void f( T parm ); где T - это некоторый тип, и функция вызывается с некоторым аргументом arg, как f( arg ); то это можно представить следующим образом void f( /* T parm */ ) { T parm = arg; //... } То есть параметры функции - это ее локальные переменные, которые инициализируются аргументами, переданными функции при ее вызове. Для функций из вашего примера это можно представить следующим образом Следующее определение функции и ее вызов void ptr(int *ptr, int d) { *ptr = d; } // ... ptr(&a, 1000); можно представить как void ptr( /* int *ptr, int d */ ) { int *ptr = &a; int d = 1000; *ptr = d; } То есть переменные ptr и d являются локальными переменными функции, которые после завершения работы функции прекратят свое существование. То же самое имеет место и для данной функции и ее вызова void ref(int &ref, int d) { ref = d; } //... ref(a, 999); Их можно представить следующим образом void ref(/* int &ref, int d */) { int &ref = a; int d = 999; ref = d; } Поэтому если вы хотите изменить исходный аргумент, то соответствующий параметр функции следует объявлять либо как ссылку на тип объекта, передаваемого в качестве аргумента, либо как указатель на тип объекта, передаваемого в качестве аргумента. Механизм объявления ссылки в качестве параметра функции обычно заключается в том, что выделяется память для ссылки в функции, и ссылка инициализируется аргументом, который в свою очередь передается через указатель на аргумент.
Комментариев нет:
Отправить комментарий