Страницы

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

понедельник, 30 декабря 2019 г.

Передача указателя или ссылки в функцию

#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; } Поэтому если вы хотите изменить исходный аргумент, то соответствующий параметр функции следует объявлять либо как ссылку на тип объекта, передаваемого в качестве аргумента, либо как указатель на тип объекта, передаваемого в качестве аргумента. Механизм объявления ссылки в качестве параметра функции обычно заключается в том, что выделяется память для ссылки в функции, и ссылка инициализируется аргументом, который в свою очередь передается через указатель на аргумент.

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

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