Является ли (* i).member менее эффективным, чем i-> member
Имея
struct Person {
string name;
};
Person* p = ...
Предположим, что никакие операторы не перегружены.
Что более эффективно (если есть)?
(*p).name
vs. p->name
Где-то в задней части моей головы я слышу звон колоколов, что оператор разрыва *
может создать временную копию объекта; это правда?
В основе этого вопроса лежат такие случаи:
Person& Person::someFunction(){
...
return *this;
}
и я начал задаваться вопросом, изменит ли результат результат на Person*
, а последняя строка просто return this
будет иметь какое-то значение (в производительности)?
Ответы
Ответ 1
Когда вы возвращаете ссылку, это точно так же, как передача указателя, исключение семантики указателя.
Вы возвращаете элемент sizeof(void*)
, а не sizeof(yourClass)
.
Итак, когда вы это сделаете:
Person& Person::someFunction(){
...
return *this;
}
Вы возвращаете ссылку, и эта ссылка имеет тот же внутренний размер, что и указатель, поэтому нет разницы во времени выполнения.
То же самое касается использования (*i).name
, но в этом случае вы создаете l-value, который затем имеет ту же семантику как ссылка (см. также здесь)
Ответ 2
Нет никакой разницы. Даже в стандарте говорится, что эти два эквивалентны, и если там есть какой-либо компилятор, который не генерирует один и тот же двоичный файл для обеих версий, он плохой.
Ответ 3
Да, его гораздо труднее читать и печатать, поэтому вам гораздо лучше использовать x->y
than (*x).y
- но помимо эффективности ввода, нет никакой разницы. Компилятору все равно нужно прочитать значение x
, а затем добавить смещение в y
, независимо от того, используете ли вы одну форму или другую (если не задействованы смешные объекты/классы, которые переопределяют operator->
и operator*
соответственно, конечно]
Определенно нет дополнительного объекта, созданного при ссылке (*x)
. Значение указателя загружается в регистр в процессоре [1]. Что это.
Возврат ссылки обычно более эффективен, поскольку он возвращает указатель (переодетый) объекту, а не делает копию объекта. Для объектов, размер которых больше размера указателя, это обычно выигрыш.
[1] Да, у нас может быть компилятор С++ для процессора, у которого нет регистров. Я знаю, по крайней мере, один процессор от Rank-Xerox, который я видел примерно в 1984 году, у которого нет регистров, он был выделенным процессором LiSP, и он просто имеет стек для объектов LiSP... Но они далеки от общего в сегодняшнем мире. Если кто-то работает над процессором, у которого нет регистров, пожалуйста, не уменьшайте мой ответ просто потому, что я не рассматриваю этот вариант. Я пытаюсь сохранить ответ простым.
Ответ 4
Любой хороший компилятор даст те же результаты. Вы можете ответить на это самостоятельно, скомпилировать оба кода на ассемблер и проверить полученный код.