2015-03-18 7 views
-1

Следующий фрагмент кода - это упрощенная версия проблемы, которую я имею в визуальной студии.Вне области до возврата

Код ввода деструктор во

return temp; 

отладки пошагового.

Код:

class point2d 
{ 
    public: 
    int x, y; 
}; 
class poly2d 
{ 
    public: 

    void operator=(const poly2d& temp) 
    { 
     for (cnt = 0; cnt < pointNum; ++ cnt) 
     { 
      p[cnt].x = temp.x; 
      p[cnt].y = temp.y; 
     } 
    } 


    poly2d(int size); 
    ~poly2d(); 

    point2d* p; 
    int pointNum; 
}; 

poly2d::poly2d(int size) 
{ 
    pointNum = size; 
    p = new point2d[size]; 
} 

poly2d::~poly2d() 
{ 
    if (p) 
    { 
     delete[] p; 
     p = 0; 
    } 
} 

poly2d copy(); 

int main() 
{ 
    poly2d myPoly(5); 

    myPoly = copy(); 

    return 1; 
} 

poly2d copy() 
{ 
    poly2d temp(5); 

    return temp; 
} 

Я знаю, эта часть не имеет никакого смысла, но это упрощено и из контекста, но в то же время подчеркивает мою проблему. Деструктор выполняется перед оператором return. Затем следует конструктор копирования, затем деструктор снова. Он дважды удаляется и вызывает ошибки. Это первый раз, когда я столкнулся с этой проблемой в течение 6 лет.

Спасибо.

+5

Это потому, что у вас нет правильного конструктора копий или оператора присваивания. Другие объяснят специфику. Если вы использовали 'std :: vector ', тогда все будет работать.Вам даже не нужно было бы предоставлять деструктор. Пусть язык сделает для вас тяжелую работу. –

+0

Какой деструктор вы имеете в виду? Локальный объект 'temp', конечно же, уничтожается, как только он выходит за рамки. – user463035818

+2

Вы возвращаетесь по значению. Вы даже назвали объект 'temp'. Почему вы думаете, что это не должно быть разрушено? Ваши ошибки не имеют ничего общего с «выходом из сферы действия» - они из-за вас нарушают правило нуля/три/пять. –

ответ

0

Вы не определили конструктор назначения копирования для своего класса poly2d. В этом случае ваш компилятор создаст для вас конструктор по умолчанию. Весь этот конструктор делает копию каждого поля вашего класса.

Это означает, в частности, что копирует указатель point2d * p, а не базовую точку.

Так что происходит, когда вы вызываете copy()?

Вы создаете новый poly2d, то есть вызывается конструктор poly2d. Это создает новый point2d. Теперь ваш вызов для копирования() завершен. То, что фактически назначено для вашего poly2d myPoly, является копией вашего временного объекта. Деструктор временного объекта вызывается сразу после завершения вызова функции copy(). Этот деструктор уничтожает объект point2d, на который указывает объект temp. Проблема в том, что ни в какой момент не был создан новый объект point2d для myPoly. myPoly имеет указатель на объект, на который указывал temp, который теперь взломан. Это, конечно, плохо.

Вы можете исправить это, указав свои собственные конструкторы назначения копирования и копирования и удостоверившись, что новый point2d создается каждый раз при копировании poly2d. Или, как уже было предложено, вы можете использовать std :: vector.

+0

Ах да. Я смешался между оператором присваивания и копией constuctor ... Я думал, что оператор void = WAS - конструктор копирования, тогда как это также просто вызывает конструктор копирования. Я не про программист, поэтому для любителей хобби я предпочел бы не использовать векторы в графических программах реального времени, поскольку они довольно дороги. Правильно, да, но дорого. – KayOL78

+0

Это также объясняет, почему я получаю 2 исполнения одного и того же деструктора. Мелкая копия скопировала переменную указателя как есть. Dangly. Спасибо всем за ваши ответы. – KayOL78

1

Вы можете попытаться реализовать Правило 3/5, но я бы рекомендовал для Rule of Zero. Он основан на следующем принципе:

классы, которые имеют пользовательские деструкторов, копирование/перемещение конструкторами или копировать/перемещать операторы присваивания должны иметь дело исключительно с правом собственности. Другие классы не должны иметь настраиваемые деструкторы, копировать/перемещать конструкторы или копировать/перемещать операторы присваивания.

Вы можете упростить свой код следующим образом:

struct point2d 
{ 
    int x, y; 
}; 

struct poly2d 
{ 
    poly2d(std::vector<point2d>::size_type size); 

    std::vector<point2d> p; 
}; 

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

poly2d(std::vector<point2d>::size_type size) 
    : p(size) 
{ 
} 
+0

Возможно, вы захотите предоставить пример реализации конструктора, чтобы помочь ему. –

+0

Почему вы используете разные типы параметров в своем примере и используете резерв вместо изменения размера? Не делайте это более запутанным, чем должно быть. –

+0

@NeilKirk Я не могу угадать намерения OP. В конце концов, это * пример *. –