Ответ 1
Это совершенно четко определено:
void something(int *x) {
reinterpret_cast<Point*>(x)->y = 42;
}
Объект Point
(p
) и его член x
являются взаимозаменяемыми по указателю, из [basic.compound]:
Два объекта a и b являются взаимозаменяемыми по указателю, если:
- [...]
- один является объектом класса стандартной компоновки, а другой - первым нестатическим элементом данных этого объекта или, если у объекта нет нестатических членов данных, любой подобъект базового класса этого объекта ([class.mem]) или:
- [...]
Если два объекта являются взаимозаменяемыми по указателю, то они имеют один и тот же адрес, и можно получить указатель на один из указателя на другой через
reinterpret_cast
.
Этот reinterpret_cast<Point*>(x)
является действительным и в конце концов имеет указатель, который указывает на p
. Следовательно, изменение его напрямую - это хорошо. Как видите, часть стандартного макета и первая часть не статических данных имеют большое значение.
Хотя это не так, как рассматриваемые компиляторы оптимизируют дополнительную нагрузку, если вы передаете указатель на p.y
и возвращаете p.x
.