Есть функция с сигнатурой:
void some_func(Object &object);
Как единственный параметр, она принимает ссылку. Создаем указатель:
Object *pObj = new Object();
Следующий шаг, логично напрашивается, что в верхнюю функцию мы должны передать ссылку, то есть:
some_func(&pObj);
Но компилятор этот вариант не принимает, а принимает такой:
some_func(*pObj);
Вопрос:
Как я понял ранее, оператор *
, это оператор разыменования и если мы передаем *pObj
, тогда передаем содержимое ссылки в функцию some_func
.
(&rObj)
some_func(*pObj)
? По моим догадкам, создается копия объекта содержимого по ссылке указателя и потом передается как параметр в метод? У вас 2 варианта. Либо использовать указатель, либо ссылку.
#include <iostream>
void some_func(int *obj){
*obj = 6;
}
void some_func2(int &obj){
obj = 5;
}
int main(){
int obj;
some_func(&obj);
std::cout<<obj;//6
some_func2(obj);
std::cout<<obj;//5
return 0;
}
&obj передаст указатель на объект, а не ссылку
Object *object = new Object();
//Создаётся указатель на новый объект
some_func(*object);
//* + (указатель на тип Object) = тип Object
//some_func принимает как аргумент объект, на который создаётся ссылка
//именно поэтому компилятор принимает такой вариант
Оператор &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) */
Поскольку функция принимает ссылку на объект Object, вы должны передавать в эту функцию объект типа Object.
Если вы передаете в такую функцию указатель на объект, это считается несоответствием типа.
Если вы делаете так:
some_func(&pObj);
То, фактически, вы передаете адрес указателя на объект типа Object. То есть, вы передаете указатель на указатель на объект типа Object.
Выражение &pObj имеет тип Object **.
&
В С++ этот токен имеет много значений:
Как бинарный оператор - оператор побитового "и".
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; // Здесь все должно быть хорошо
}
}
Также указатель можно переназначить, но в случае передачи указателя в функцию это не имеет значения. Есть еще ряд других случаев когда ссылки и указатели служат совсем разным целям, но это повод для отедльной статьи.
Для отладки программы необходимо приостанавливать работу программы, порционно выводить некоторую информацию на экран и затем по команде...
Создать программу, которая демонстрирует, что функция со своим собственным try-блоком не должна перехватывать все возможные исключения, выброшенные...
Изучаю работу с g++ интересует линковка, генерация кода, оптимизация, g++ содержит множество флагов оптимизаций помимо -O1