2016-01-08 4 views
0

Я имею класс Place с такими методами:C++ конструктор копирования и указатель

class Place{ 

    protected: 
    Keypoint* _kp; 

    Place() { 
     Keypoint* kp = new Keypoint(); 
     _kp = kp; 
    }; 
    Place(const Place& cSource){ 
     delete _kp; 
     _kp = cSource.makePointer(); 

     } 
    virtual ~Place(){ 
     delete _kp; 
    } 

    virtual Keypoint* makePointer() const { 
     return _kp->makePointer(); 
    } 


}; 

Таким образом, конструктор, деструктор и метод копирования.

В моем основном я делаю что-то простое, как AASS::graphmatch::Place ppp; AASS::graphmatch::Place p2(ppp);, чтобы попробовать конструктор копирования, и у меня есть огромный segfault с valgrind, который говорит мне, что я использую Conditional jump or move depends on uninitialised value(s) после удаления в копии. Метод makePointer в Keypoint делает new и возвращает указатель Keypoint*.

virtual Keypoint* makePointer() const { 
    Keypoint* d = new Keypoint(); 
    return d; 
} 

Это мое понимание того, что каждый новый должен быть освобожден с помощью удаления так, поэтому я использую удалить перед вызовом makePointer. Поэтому я начинаю с удаления _kp, чтобы выпустить старую память, а затем присваиваю ей вновь созданный указатель.

Я не могу понять, почему у меня есть неинициализированное значение?

+1

, когда вы 'удалить _kp;' в конструкторе копирования, то '_kp' не отформатирована для нового объекта еще, так что вы пытается «удалить» ' – BeyelerStudios

+0

Действительно ли это конструктор копирования? Кажется, что Keypoint по умолчанию создается каждый раз (если вы не используете какую-то невидимую глобальную переменную). Это, кажется, нарушает принцип 'x == y' ... – patrik

+0

Я не уверен, что в этом случае принцип' x == y': S, но я делаю это то, что у меня есть класс, наследующий от Keypoint и создайте указатель на свой класс, используя makePointer(). Поэтому в зависимости от типа cSource я получаю указатель класса cSource, который также является Keypoint. – Malcolm

ответ

3

В своем конструкторе копирования вы вызываете delete _kp;. Но _kp не был инициализирован в этот момент.

Это не будет хорошо.

Удалить строку delete _kp;. А еще лучше, рассмотреть вопрос об использовании базового элемента инициализации:

Place(const Place& cSource) : _kp(cSource.makePointer()) 
{ 
} 

Даже лучше, чем, рекомендуется использовать управляемый класс указатель, как std::unique_ptr для Keypoint члена.

3

Вы написали свой конструктор копирования, как будто это оператор присваивания:

Place(const Place& cSource){ 
    delete _kp; 
    _kp = cSource.makePointer(); 

    } 

Вам может понадобиться оператор присваивания, и вам может понадобиться конструктор копирования. Но это не одно и то же.

При входе в конструктор копирования _kp держит мусор, так что delete является ошибкой.

1

Вы удалить uninitialzed указатель в конструкторе копирования:

Place(const Place& cSource){ 
    // delete _kp; // _kp is not initialized 
    _kp = cSource.makePointer(); // now _kp gets initialized 
} 
Смежные вопросы