Вопрос по 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 );
Комментариев нет:
Отправить комментарий