Страницы

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

среда, 10 октября 2018 г.

Передача указателей в функцию C++

Вопрос по C++. При передаче обычной переменной в функцию создается, как я понимаю, её копия. А что происходит, когда мы передаем указатель? Создается ли копия указателя или нет?


Ответ

Если у вас объявлена функция с параметром, как, например,
void f( T t );
где T - это некоторый тип, и эта функция вызывается с некоторым выражением, переданным ей в качестве аргумента, как
f( exp );
то инициализацию параметра можно представить следующим образом
void f( /* T t */ ) { T t = exp; //...
то есть параметр - это локальная переменная функции, которая инициализируется тем выражением, которое передано функции в качестве аргумента. Следовательно изменения параметра никак не сказываются на исходном аргументе, ели только тип T не является ссылочным типом.
Сравните две функции
void f( int *p ) { p = new int( 10 ); }
void g( int * &p ) { p = new int( 10 ); }
и их вызов
int main() { int *p = nullptr;
f( p );
if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl;
g( p );
if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl;
delete p; }
В этом примере при вызове функции f имеет место утечка памяти, так как память, распределенная в функции, не освобождается. Параметр функции - локальная переменная p - при выходе из функции удаляется, и тем самым адрес выделенной динамически памяти будет утерян.
У функции g параметр имеет ссылочный тип, то есть эта ссылка на переданный функции аргумент. Поэтому функция имеет дело с исходным аргументом и меняет его в своем теле, присваивая ему адрес выделенной памяти.
Также можно передать указатель на указатель, если требуется изменить исходный указатель в функции. Например,
void h( int **p ) { *p = new int( 10 ); }
Вызов функции будет выглядеть как
h( &p );

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

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