2012-06-13 2 views
3

Если я не использую new для распределения элементов данных класса, существует ли какая-либо очистка, которая должна быть выполнена в деструкторе? Например, в следующем случае мне понадобится delete вектор? Или это зависит от MyType?Нужно ли мне очищать элементы данных, отличные от указателей?

class A { 
    A(); 
    ~A(); 
    MyType x; 
    std::vector<MyType> v; 
}; 
A::A() { 
    x = MyType(42); 
    v = std::vector<MyType>(5); 
} 
A::~A() { 
    // what goes here? 
} 

ответ

9

Должно быть педантичным, от на каких MyType есть. Если у вас есть typedef char* MyType и вы выделяете память для MyType, и вы хотите, чтобы эта память принадлежала объекту, тогда да, вам нужен деструктор.

В противном случае вам не нужно освобождать память для всего, что не было выделено new или malloc, так что нет.

У вашего класса вообще не должно быть деструктора. Существует общее мнение, что у вас должен быть только деструктор, когда он вам действительно нужен. Наличие деструктора также подразумевает реализацию оператора присваивания и конструктора копирования (правило 3). Если вы не управляете какой-либо памятью, лучше полагаться на предоставленные компилятором, то есть компилятор будет генерировать этих трех, если вы этого не сделаете.

Кроме того, ваш конструктор должен выглядеть следующим образом:

A::A() : x(42), v(5){ 
} 

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

+0

В этом конкретном случае нет необходимости в dtor. Просто имейте в виду, что «R» в «RAII» означает * ресурс *, а не * память *. Иногда вам нужно выпустить что-то другое, кроме памяти в dtor. –

+0

@JohnDibling, но эта (по крайней мере вторая часть) основана на предположении, что ресурсы освобождаются, когда их отдельные владельцы уничтожаются. Поэтому, если 'MyType' приобретает ресурс и освобождает его в своем деструкторе, все в порядке. –

+0

Да, я больше делал этот комментарий для будущих читателей. :) –

1

Деструкторы автоматически вызываются, поэтому вам не нужно это делать. Кроме того, для указателей используйте smart pointers (например, std::unique_ptr) вместо delete вручную.

class A { 
    A(); 
    ~A(); 
    MyType x; 
    std::vector<MyType> v; 
}; 
A::A() : x(42), v(5) { } 
A::~A() { 
    // x.~MyType() implicitly called. 
    // v.~std::vector<MyType>() implicitly called. 
} 
4

Ваш класс не нуждается в явном деструкторе. В любом случае дескриптор vector будет вызываться автоматически. А поскольку сам векторный объект (в отличие от внутренних данных) не является динамическим, вам не нужно delete. Фактически, это будет синтаксическая ошибка, так как v не является указателем.

+0

Значит, «правило из трех» не применяется в этом случае, поскольку мне нужен только явный конструктор? – Andreas

+0

Правило 3 - копия ctor, dtor и перегрузка =. Не другие ctor's. – djechlin

+0

@djechlin: Ох. В этом есть смысл. – Andreas

0

Нет, вам не обязательно. Их конструкторы будут называться неявно.

1

Этот вектор автоматически удаляется в момент разрушения. Однако, если вы храните указатели в векторе, например. Если вы скажете вектор < Foo * > v ;, вам нужно написать код, чтобы удалить указатели в векторе. Один из способов избежать этого использовать векторные < зЬй :: unique_ptr <Foo> > или вектор < станд :: shared_ptr <Foo> >

0

Для класса нет, вы этого не сделаете, так как он не имеют какой-либо элемент указателя, выделенный с использованием новых или malloc.

Учтите, что если ваш класс/структура MyType есть указатели в качестве члена, деструктор MyType является ответственным, чтобы освободить память такого указателя, но вам не придется беспокоиться с этим в классе A, так как при вызове его деструктора деструктор вектора вызывает деструктор MyType.

+0

Если «MyType» не является указателем, в этом случае не вызывается деструктор, и вы будете утечки памяти. –

+0

@LuchianGrigore Правильно ли, что 'MyType' может быть только указателем, если он был' typedef'fed? – Andreas

+0

@ Andreas или с определением '#define MyType X *' :) –

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