Странные результаты с созданием объекта и связыванием

По ошибке я написал что-то глупое, что к моему удивлению сработало.

class A
{    public:
void print()
{
std::cout << "You can't/won't see me !!!" << std::endl;
}
A* get_me_the_current_object()
{
return this;
}
};
int main()
{
A* abc = dynamic_cast<A*>(abc);
abc->print();
}

Вот, A* abc = dynamic_cast<A*>(abc)Я делаю dynamic_cast для указателя, который не объявлен. Но это работает, поэтому я предположил, что приведенное выше утверждение нарушается как:

A* abc;
abc = dynamic_cast<A*>(abc);

и, следовательно, это работает. Однако, попробовав несколько более странных сценариев, таких как:

A* abc;
abc->print();

и далее

A* abc = abc->get_me_the_current_object();
abc->print();

Я был ошеломлен, глядя на то, как эти примеры работали, и отображение было сделано.
Может кто-нибудь рассказать, как это работает? Заранее спасибо.

0

Решение

Вы сделали общую ошибку, считая, что неопределенное поведение и ошибки в C ++ означают, что вы должны ожидать резкого сбоя или возгорания вашего компьютера. Иногда ничего не происходит. Это не означает, что код «работает», потому что в нем все еще есть ошибка, просто симптомы не проявляются … еще.

Но это работает, поэтому я предположил, что приведенное выше утверждение нарушается как:

Да, все, что вы делаете, это конвертируете неинициализированный указатель в один и тот же тип, то есть конвертация не требуется, поэтому компилятор ничего не делает. Ваш указатель все еще того же типа и все еще неинициализирован.

Это похоже на это:

int i = i;

Это верно в соответствии с грамматикой C ++, потому что i в данный момент находится в области видимости, но не определен, поскольку копирует неинициализированный объект. Это вряд ли на самом деле подожжет ваш компьютер, хотя, кажется, «работает».

Может кто-нибудь рассказать, как это работает?

Технически вы разыменовываете недействительный указатель, который является неопределенным поведением, но поскольку ваши функции-члены фактически не используют никаких членов объекта, недействительный this указатель не разыменовывается, поэтому код «работает» (или, по крайней мере, отображается как.)

Это похоже на:

void function(A* that)
{
std::cout << "Hello, world!\n";
}
A* p;
function(p);

Поскольку that указатель не используется (как this указатель не используется в ваших функциях-членах) это не обязательно приводит к сбою, хотя это может происходить в реализациях, где даже копирование неинициализированного указателя может вызвать аппаратную ошибку. В вашем примере кажется, что ваш компилятор не нуждается в разыменовании abc вызвать нестатическую функцию-член и передать ее как скрытую this Параметр не вызывает аппаратного сбоя, но поведение по-прежнему не определено, даже если он не дает сбоя очевидным образом, например, в случае segfault.

6

Другие решения

abc неинициализирован и указывает на неопределенное место в памяти, но ваши методы ничего не читают из *this чтобы они не разбились.

Тот факт, что они не потерпят крах, почти наверняка является поведением, определяемым реализацией.

3

По вопросам рекламы [email protected]