Члены указателя класса C++ ведут себя странно (ошибка)

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

class whathappened {
public:
    int * a;
    whathappened();
    void print();
};

whathappened::whathappened() {
    int b = 23;
    a = &b;
}

void whathappened::print() {
    cout << a << " " << *a << endl;
}

int main() {
    whathappened sam;
    cout << sam.a << " " << *sam.a <<  endl;
    sam.print();
    cout << sam.a << " " << *sam.a << endl;
    while (1) {}
}

0133F650 23
0133F650 -858993460
0133F650 -858993460

3 ответа

Указатель a в вашем примере указывает на значение, которое выходит за рамки после конструктора. Сам указатель остается неизменным, но значение, вероятно, перезаписывается другими значениями в стеке при вызове большего количества функций.

В любое время возвращение ссылки на объект локальной функции вызовет неопределенное поведение, например указатель ( в большинстве случаев).

стандарт N4727- 6.6.3/7

после окончания срока службы объекта и до повторного использования или освобождения хранилища, в котором занятый объект, может использоваться любое значение glvalue, которое ссылается на исходный объект, но только ограниченным образом... Программа имеет неопределенное поведение, если: 1. glvalue используется для доступа к объекту 2.....

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

Если какой-либо указатель указывает адрес памяти какой-либо переменной, но после того, как какая-то переменная была удалена из этой ячейки памяти, тогда как указатель все еще указывает на эту ячейку памяти. Такой указатель известен как висячий указатель, а эта проблема известна как проблема висячего указателя.

А по поводу справки:

Хотя ссылки, будучи инициализированными, всегда ссылаются на действительные объекты или функции, можно создать программу, в которой время жизни упомянутого объекта заканчивается, но ссылка остается доступной (висящая). Доступ к такой ссылке - неопределенное поведение.

Если вы выделяете b на кучу, то поведение будет ожидаемым, как

whathappened::whathappened() 
{
   int *b = new int(23); 
   a = b;
}

ИЛИ, вы можете просто сделать

whathappened::whathappened() 
{
   a = new int(23); 
}

В этом случае не беспокойтесь о масштабах b, Назначая a = b мы сказали a указать память, которая находится в куче. И это будет действовать до тех пор, пока мы не вызовем удаление на a, Чтобы освободить память, указанную a вам нужно позвонить удалить. лайк

whathappened::~whathappened() 
{
    delete a;
}
Другие вопросы по тегам