Это зависит от того, что вы делаете с разыменованным указателем. Сама операция разыменования ничего не делает сама по себе. Он просто получает значение типа T
, представляющее ваш объект, если указатель имеет значение T*
struct a {
int big[42];
};
void f(a * t) {
// does nothing. Only interesting for standard or compiler writers.
// it just binds the lvalue to a reference t1.
a & t1 = *t;
}
Если вы на самом деле получаете значение из этого объекта, обозначенного lvalue, возвращаемым операцией разыменования, компилятор должен скопировать данные, которые содержит объект. Для простого POD это просто memcpy
:
a aGlobalA;
void f(a * t) {
// gets the value of of the object denoted by *t, copying it into aGlobalA
aGlobalA = *t;
}
Мой порт gcc выводит этот код для f:
sub $29, $29, 24 ; subtract stack-pointer, creating this frame
stw $31, $29, 20 ; save return address
add $5, $0, $4 ; copy pointer t into $5 (src)
add $4, $0, aGlobalA ; load address of aGlobalA into $4 (dst)
add $6, $0, 168 ; put size (168 bytes) as 3rd argument
jal memcpy ; call memcpy
ldw $31, $29, 20 ; restore return address
add $29, $29, 24 ; add stack-pointer, destroying this frame
jr $31
Оптимизированный машинный код будет использовать встроенный код вместо вызова memcpy
, но это на самом деле просто деталь реализации. Важно то, что просто *t
не выполняет какой-либо код, но для доступа к значению этого объекта на самом деле нужно его скопировать.
Если бы мы имели дело с типом, имеющим пользовательский оператор назначения копирования, дела более сложны:
struct a {
int big[42];
void operator=(a const&) { }
};
Код для той же функции f
теперь выглядит так:
sub $29, $29, 8
add $29, $29, 8
jr $31
Хах. Но это не было таким сюрпризом, не так ли? В конце концов, компилятор должен вызывать наш operator=
, и если он ничего не делает, вся функция также ничего не делает!
Заключение
Я думаю, что мы можем сделать вывод, все зависит от того, как используется возвращенное значение operator*
. Если у нас есть только указатель, на который мы обращаемся, мы видим выше, что сгенерированный код во многом зависит от обстоятельств. Я не показал, как он ведет себя, если мы разыменовываем тип класса, перегруженный operator*
. Но по сути, он просто ведет себя так, как мы видели с operator=
. Все измерения были выполнены с -O2
, поэтому компилятор правильно указывает:)