Трик за данните
Вашият трик се основава на предположения за разположението на паметта на вашия обект. За щастие за вашия конкретен пример, с вашия компилатор изглежда работи.
Ако компилирам този код с MSVC2013, той изобщо не работи!! В крайна сметка бих могъл да разбера, че работи, когато използвам масив от short
вместо int
, ако сложа някои съвети в конструктора:
A(int t) { a = t; cout << "A: " << (void*)this << " a: " << (void*)&a << " rel:" << (char*)&a - (char*)this << endl; }
Заключение: Не можете да разчитате на това като цяло (и дори не за вашия компилатор в по-сложни примери). Стандартът дава много ограничена гаранция за относителните адреси на паметта на членовете :
Раздел 9.2/15: Членовете с нестатични данни на клас (без обединение) със същия контрол на достъпа се разпределят, така че по-късните членове да имат по-високи адреси в обект на клас. Редът на разпределяне на нестатични членове на данни с различен контрол на достъпа не е определен. Изискванията за подравняване на изпълнението може да накарат два съседни члена да не бъдат разпределени непосредствено един след друг; (...)
Освен това вашият трик може да създаде псевдоним на указател. Така че компилаторът прави предположение за вашите указатели и членовете на вашия обект, които може да не са валидни, причинявайки неуспех на генерираните оптимизации.
Трик за функции
За адреса на вашата функция е още по-лошо. Това отново не е дефинирано в стандарта и е специфично за изпълнението.
Често използваната реализация за виртуални функции се основава на специфични за класа vtables. Всеки полиморфен обект има някъде в класа указател към своята vtable (обикновено в първите няколко байта на обекта.
Относителната позиция на указателя на функцията във vtable зависи от всички виртуални функции на класа и всички наследени класове. За вашия пример, с MSVC2013 мога да успея да извикам функцията:
typedef int (A::*fptr)();
fptr pf = (*(fptr**)x)[0]; // first unction in vtable
(x->*pf)(); // call it.
Но разбира се това е напълно нестандартно и изключително опасно!
И имайте предвид, че за невиртуални функции изобщо не можете да получите адреса от обекта.
person
Christophe
schedule
24.02.2015