В чём отличие между выводом f и *&f в функции, принимающей ссылку?

131
24 июля 2019, 09:30
void foo(int& f){
   cout << f << endl;
}
void foo1(int& f){
   cout << *&f << endl;
}

Есть ли в этих записях различия? Выводят они одно и то же значение. Но может различие где-то глубже? А также в таком случае:

void foo(int*& f){/* ... */}
void foo1(int& f){/* ... */}

Записи будут эквивалентными, не учитывая, что придётся разыменовывать f, чтобы получить значение? Что использовать лучше? Я так понял, вторую функцию лучше использовать, если мы передаём переменные, а первую, когда работаем с массивом. Поправьте, если не прав.

Answer 1

Если речь идет о ссылке на фундаментальный тип, такой как int &f, то никакой разницы между f и *&f нет. Разницы нет не только с точки зрения наблюдаемого значения, но и с точки зрения наблюдаемого объекта. Но если заменить тип int на класс-тип, то благодаря перегрузке операторов разница может быть сколь угодно большой. Из вашего вопроса не понятно, связан ли он именно с типом int или нет.

О какой "эквивалентности" вы спрашиваете во втором случае - не ясно, ибо параметры функции ссылаются на совершенно разные сущности. Никакой логики в утверждении "вторую функцию лучше использовать, если мы передаём переменные, а первую, когда работаем с массивом" я не вижу.

Answer 2
void foo(int*& f) 

тут аргументом является неконстантная ссылька на указатель, поэтому вы можете выполнить действия над указателем в теле функции, и тогда изменения произойдут с тем указателем, которую вы передадите:

{     
    ++f; 
}

Но передавать в функцию имя массива вы не сможете, поскольку имя массива связана с определенным количеством элементов, и потому может рассматриваться как константная ссылька. Т.е. в следующую функцию:

void foo1(int* const& f)
{ cout << *(f + 1) << " : " << *f << endl; }

вы можете передать имя массива. Тип аргумента не разрешает выполнить действия с самым указателем, а (f + 1) это уже другой указатель.

В следующую функцию:

void foo2(int* f){ ++f;  }

вы можете передать и имя массива и любой указатель, поскольку аргумент это другой указатель, инициализированный тем же адресом.(происходит копирование)

И, наконец:

void foo3(int& f) { ++f;  }

Имеет аргумент_ссыльку на обьект. Т.е. в функцию моожно передавать обьект, и все изменения произойдут именно с этим обьектом. В данном случаи инкрементируется значение обьекта.

Для того, чтобы лучше понять все это, напишите для себя тестовую программу. Например:

int a[] = {10, 20, 30};
int *m = a;
foo2(m);
cout << *m << " ... " << *a << endl;
foo1(a);
cout << *m << " ... " << *a << endl;
foo(m);     
foo(a) // error
foo2(a);
cout << *m << " ... " << *a << endl;
foo3(a[1]);
cout << *m << " ... " << *a << endl;
READ ALSO
Метод drawImage()

Метод drawImage()

Какие аргументы использует метод drawImage()? Знаю первые 3, но что насчёт четвертого? В API подробной информации не нашел

122
Android. Как сгенерировать видео программно?

Android. Как сгенерировать видео программно?

Мне необходимо генерировать видео передвижений элементов по экрануНагуглил два варианта: 1

143
Удаление фигур java

Удаление фигур java

Можете подсказать метод для удаления фигуры? Если для рисования используется paintComponent(), который вызывается автоматически, то что делать с удалением?...

151
Custom error message удаление лишних полей

Custom error message удаление лишних полей

В rest api решил сделать custom exception handler через @ControllerAdviceИ хотел, чтобы клиент получал, например, лишь 3 поля моего класса Exception

162