Адрес указателя и путаница - PullRequest
       3

Адрес указателя и путаница

0 голосов
/ 19 февраля 2019

У меня есть два почти идентичных фрагмента кода, которые должны выдавать один и тот же вывод, за исключением того, что они не только разные, но одна измененная строка как-то влияет на несвязанный вывод!

#include "stdafx.h"
#include <iostream>

using namespace std;

class Tag {
public:
    int num = 0;
    Tag* contains = nullptr;

    Tag::Tag(int n) { num = n; }

    void setContains(Tag t) { contains = &t; }

    int getNum() { return num; }
    Tag getContains() { return *contains; }
};

int main() {
    Tag tag1 = Tag(1); Tag tag2 = Tag(2);
    tag1.setContains(tag2);
    cout << tag1.getContains().getNum() << endl << (*tag1.contains).getNum() << endl;
    return 0;
}

Это выводит

8460735
8460735

или другое случайное число.Что говорит мне, что я каким-то образом выводю адрес указателя, а не объект, на который он ссылается.Поэтому я изменил строку

cout << tag1.getContains().getNum() << endl << (*tag1.contains).getNum() << endl;

на

cout << tag1.getContains().getNum() << endl << (*tag1.contains).num << endl;

и получаю вывод

2
2

Подождите, что?Я понял, если вторая строка изменится с адреса на фактическое число 2, но почему ОБА меняется на 2?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Поскольку вы вызываете неопределенное поведение, вы сохраняете адрес локального аргумента в Tag* contains здесь:

void setContains(Tag t) { contains = &t; }

Вы должны передать аргумент по ссылке или по указателю напрямую.В противном случае вы просто сохраняете адрес переменной в стеке, которая уничтожается при выходе из функции.

Все, что в дальнейшем основано на contains, является просто неопределенным поведением.

0 голосов
/ 19 февраля 2019

setContains указывает contains на локальную переменную.Переменная уничтожается, как только функция возвращается, оставляя contains висячий указатель.Любая попытка использовать его затем демонстрирует неопределенное поведение.

На практике contains->num читает некоторый случайный мусор из стека, в котором находилась переменная.Незначительные возмущения в программе меняют шаблоны доступа к стеку, оставляя там различный мусор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...