#cpp
Есть функция с сигнатурой: void some_func(Object &object); Как единственный параметр, она принимает ссылку. Создаем указатель: Object *pObj = new Object(); Следующий шаг, логично напрашивается, что в верхнюю функцию мы должны передать ссылку, то есть: some_func(&pObj); Но компилятор этот вариант не принимает, а принимает такой: some_func(*pObj); Вопрос: Как я понял ранее, оператор *, это оператор разыменования и если мы передаем *pObj, тогда передаем содержимое ссылки в функцию some_func. Почему вариант с указателями работает именно так? Почему мы не можем в метод с таким параметром передать ссылку? (&rObj) Что происходит при передаче some_func(*pObj)? По моим догадкам, создается копия объекта содержимого по ссылке указателя и потом передается как параметр в метод?
Ответы
Ответ 1
Токен & В С++ этот токен имеет много значений: Как бинарный оператор - оператор побитового "и". 0b0011 & 0b0110; // 0b0010 Как унарный оператор - оператор взятия адреса у переменной. Type a; Type * ap = & a; // указатель на переменную типа Type Как часть объвления типа - модификатора типа. Type & r; // ссылка на переменную типа Type Токен * Этот токен имеет такой же набор значений Как бинарный оператор - оператор умножения. 3 * 5; // 15 Как унарный оператор - оператор разыменовывания (взятие значения) переменной. Type a; Type & ar = * a; // ссылка на переменную типа Type Как часть объвления типа - модификатора типа. Type * r; // указатель на переменную типа Type Ссылки как значения Работа с ссылками это как работа с их значениями. Нельзя переопределить ссылку чтобы она указывала на другой объект. Почти весь синтаксис для ссылки и для переменной значения одинаковый. Ссылки обяъвляются как Type & name. И в дальнейшем ведут себя как обычные пермененые содержащие значение. struct Type { int a; } Type o; Type & r = o; o.a = 1; // ok r.a = 2; // ok Переменную-ссылку можно присвоить обеъкту и наоборот: Type & ref = o; Type val; ref = val; val = ref; Передача как аргумент функции тоже явлется присваиванием так что предыдущее верно и для них: void fun1(Type x) {} fun1(o); // ok fun1(r); // ok void fun2(Type & y) {} fun2(o); // ok fun2(r); // ok Почему нельзя присвоить указатель ссылке. Одна из наиболее важных причин для этого заключается в том, что указатель может содержать адрес не валидного объекта. Этот процесс отдан программистам: void funcp(Type* p) { if (p == nullptr) { Type & r = &p; // Здесь ОС пошлет сигнал и программа аварийно завершится } else { Type & r = &p; // Здесь все должно быть хорошо } } Также указатель можно переназначить, но в случае передачи указателя в функцию это не имеет значения. Есть еще ряд других случаев когда ссылки и указатели служат совсем разным целям, но это повод для отедльной статьи.Ответ 2
Оператор &something - это оператор получения адреса something. Поэтому когда вы пишете &pObj, а pObj - указатель, вы передаете адрес указателя, а функция у вас принимает адрес какой-то переменной. Оператор * разыменовывания указателя дает вам доступ к памяти, на которую указатель указывает, можно сказать, что вы как-будто получаете какую то переменную. И затем, при передаче в вашу функцию, ее тип неявно преобразуется к ссылке. bar(int& u); int obj; int* pointer = &obj; bar(*pointer); // => bar(obj) bar(obj); // то, что вы хотели bar(pointer); // функция принимает аргумент типа int, а не int*. Ошибка. bar(&pointer); /* передаст адрес указателя, это подойдет, если bar принимает указатель на указатель: bar(int** u) */ bar(&obj); /* передаст адрес obj, это подойдет, если bar принимает указатель: bar(int* u) */Ответ 3
У вас 2 варианта. Либо использовать указатель, либо ссылку. #includevoid some_func(int *obj){ *obj = 6; } void some_func2(int &obj){ obj = 5; } int main(){ int obj; some_func(&obj); std::cout< Ответ 4
Поскольку функция принимает ссылку на объект Object, вы должны передавать в эту функцию объект типа Object. Если вы передаете в такую функцию указатель на объект, это считается несоответствием типа. Если вы делаете так: some_func(&pObj); То, фактически, вы передаете адрес указателя на объект типа Object. То есть, вы передаете указатель на указатель на объект типа Object. Выражение &pObj имеет тип Object **.
Комментариев нет:
Отправить комментарий