Зачем нужны ссылки на указатели? С++
Наткнулся на вот такой код, который, как я понимаю, создает указатель и ссылку на этот указатель:
int* int_ptr = &x;
int*& strange_ref = int_ptr;
Отсюда вопрос, зачем в С++ вообще существует подобный синтаксис, ведь strange_ref, несмотря на то, что является типом int*&, все равно будет иметь такой же функционал, как и int*. Все также можно будет разыменовать эту ссылку и тд. Почему этот синтаксис вообще существует и где он применяется?
Ответы (4 шт):
несмотря на то, что является типом int*&, все равно будет иметь такой же функционал, как и int*
А вот и нет.
int x = 1, y = 2;
int *a = &x;
int *b = a;
int *&c = a;
a = &y;
std::cout << *b << '\n'; // 1
std::cout << *c << '\n'; // 2
Ну вот конкретный практический пример: типичная функция навроде swap без проблем работает с указателями, принимая их по ссылке, как и другие объекты:
template<typename T>
void swap(T & left, T & right)
{
T tmp{left};
left = right;
right = tmp;
}
Или несколько операций с предварительно выбранным одним указателем:
int * p1{};
int * p2{};
int * & pcur{cond ? p1 : p2};
... // много операций, изменяющих pcur;
Собственно указатели являются такими же объектами, как и все остальные, и для них можно использовать все те же сценарии работы со ссылками.
Ссылка на указатель оправдана, например, если она параметр функции или операнд перегруженного оператора. Да, эта ссылка имеет синтаксис не целевой величины, а указателя. Но если функция должна не взять готовый указатель у вызывающего кода, а вернуть его в вызывающий код, но сделать это через параметр, то по указателю это сделать нельзя, так как он указывает на целевую величину, а не на указатель.
size_t f(int *p)
{
size_t s;
s=(512+((rand())% 1024));
p=new int [s];
return s;
}
int main ()
{
int *x;
int *y;
f(x);
return 0;
}
Здесь p – указатель не на x, а на память, выделенную оператором new. А где лежит x? Функции надо знать именно это, только тогда она сможет положить в этот x указатель на память, выделенную оператором new. Куда класть адрес выделенной памяти? В x? Или в y?
size_t f(int *&p)
{
size_t s;
s=(512+((rand())% 1024));
p=new int [s];
return s;
}
int main ()
{
int *x;
int *y;
f(x);
delete [] x;
return 0;
}
А вот здесь всё в порядке, p – ссылка на x, теперь можно в этот x положить значение, возвращённое оператором new. А вот x уже будет указателем на память, выделенную по new. Или Вы не это имели ввиду?
Могу дополнить уже данные ответы своей интерпретацией. Возможно кому-то так будет проще разобраться.
Смысл ссылки на указатель в том чтобы работать с исходным указателем. дело в том, что если передать просто указатель - это работает как передача по значению, то есть изменения переданного указателя внутри метода или функции не приводят к изменению значения исходного (переданного) указателя. изменится только его локальная копия. если вам нужно модифицировать не объект, расположенный в памяти на которую указывает аргумент, а сам адрес на который указывает аргумент - кажется нет другого выхода кроме как передавать указатель по ссылке (ссылку на указатель). да, синтаксис при этом останется как при использовании обычного указателя.