2013-02-16 2 views
0

Я только начал изучать C++, и сейчас я работаю с указателями. Я не понимаю, почему происходит следующее.Указатели на C++; ошибка сегментации:

Итак, скажем, у меня есть два класса A и B. A имеет целое поле (int valueA) и B имеет поле указателя (до A), A * a. Ниже я показал оба класса.

class A{ 
    A::A(int value){ 
    valueA = value; 
} 


void A::displayInfo(){ 
     cout<<A<<endl; 
    } 
} 



class B{ 

    B::B(){ 
    a=0; 
    } 


    void B::printInfo(){ 
     a -> displayInfo(); //Segmentation fault 
    } 

    void B::process(){ 
    A new_A = A(5); 
    a = &new_A; 
    new_A.displayInfo(); //correct output 
    a -> displayInfo(); //correct output 
    } 
    } 

Теперь, когда в моем главном классе я сделать следующее: создать экземпляр класса B и вызвать процесс() и печать() функции. На выходе я получаю: 5 (это правильно), 5 (что правильно) и ошибка сегментации. Может ли кто-нибудь помочь мне понять, почему это происходит? Согласно моему нынешнему пониманию указателей, я делаю правильную вещь?

INT основной (аннулируются) {

B b_object(); 
b_object.process(); 
b_object.print(); 

}


Просто, чтобы сделать это ясно, у меня есть файл хиджры и B.h где я декларировать "ИНТ значение а;" и "A * a;" соответственно. И я знаю, что это можно сделать гораздо проще, без указателей, но я стараюсь, чтобы узнать, как здесь работают указатели: D

+0

Вы потеряли точки с запятой после определений классов, и вы не должны использовать 'Class :: Method' _inside_ определение класса. –

+0

Я редактировал код для форматирования, оставив ошибки нетронутыми. –

+0

@MartinshShaiters: Нет, нет. –

ответ

3
A new_A = A(5); 
a = &new_A; 

Здесь вы создаете new_A, который является локальным для process и присвоить его адрес a. Когда функция process заканчивается, new_A выходит за пределы области действия и уничтожается. Теперь a указывает на недопустимый объект.

Реальное решение здесь заключается в том, чтобы не использовать указатели, подобные этому, но если вам действительно нужно, чтобы иметь что-то последнее, выходящее за пределы функции, вам необходимо динамически распределить его. Сделайте это с помощью a = new A(5);. Вы должны убедиться в том, что у вас delete a; в какой-то более поздний момент в программе, иначе динамически выделенная память будет просочиться.

+0

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

+0

Думаю, теперь я понимаю, по крайней мере, почему он не работает. И да, вы правы, делая «a = новый A (5)»; решает проблему. Но есть ли способ создать новый экземпляр A (скажем new_A) и обновить указатель (a), чтобы указать на этот новый экземпляр? – FranXh

+0

@FranXh Ну, это то, что вы делали раньше. Проблема заключалась в том, что время жизни объекта было меньше времени жизни указателя.Указатель продолжал указывать, где был объект, даже после того, как объект вышел из сферы действия. Другой способ гарантировать, что срок службы объекта длится достаточно долго, - это передать его 'process' по ссылке. Затем вы можете взять адрес этой ссылки и до тех пор, пока объект, на который ссылается, длится достаточно долго, вы будете в порядке. –

0

присваивается локальной переменной в процессе(), следовательно, не действует в Принтинфо()

0

переменная a является локальной для ваших методов - объявить его на уровне класса

+0

Я объявил это в моем файле B.h, поэтому a не является локальным – FranXh

+0

Вероятно, вы должны показать соответствующую информацию (объявления переменных) в фрагменте кода. Здесь может быть областью переменной. – Floris

+0

Ok Я отредактировал вопрос – FranXh

Смежные вопросы