2011-01-25 2 views
4

Эти вопросы относительно просты. При использовании векторов следует использовать оператор new при нажатии нового элемента? И какой метод выпуска я должен позвонить? Вот что я имею в виду:Новый оператор с векторами

// Release method: 1. 
void ReleaseMethodOne(vector< int * > &ThisVector) 
{ 
    // Clear out the vector. 
    ThisVector.clear(); 
    return; 
} 

// Release method: 2. 
void ReleaseMethodTwo(vector< int * > &ThisVector) 
{ 
    // Clear out the vector. 
    for(unsigned uIndex(0); uIndex < ThisVector.size(); uIndex++) 
    { 
     delete ThisVector.at(uIndex); 
    } 
    return; 
} 

int main() 
{ 
    vector< int * > Vector; 

    // Add a new element. 
    Vector.push_back(new int(2)); 

    // More code... 

    // Free the elements before exiting. Which method should I call here? 
    ReleaseMethodOne(Vector); // This one? 
    ReleaseMethodTwo(Vector); // Or this one? 

    return 0; 
} 

Я начал изучать векторы, не так давно, и книга, которую я узнавал от сказал, что clear() метод вектора назвал каждый из деструктора элементов. Это относится к оператору new?

ответ

5

STL контейнеры магазин экземпляры объектов, которые вы им указываете, указатели в вашем примере. Они никогда не выпускают память вы явно выделены. Вы должны освободить эту память самостоятельно, поэтому необходимо использовать второй метод «выпуска».

Конечно, вам не нужно new каждые int. Просто используйте vector<int> - вам не придется иметь дело с ручным управлением памятью вообще.

+0

+1 для обозначения правильного пути создания вектора ints. – Kleist

2

Вы должны использовать ReleaseMethodTwo(), потому что если вы выделили память, то это ваша ответственность, чтобы удалить его.

std::vector::clear() только стирает элементы из вектора. Он не вызывает delete об элементах, которые стираются!

2

За то, что вы там делаете, вам нужно будет использовать ReleaseMethodTwo. То, что это означает, говоря, что он вызывает деструктор элемента, состоит в том, что содержащиеся в нем классы (не содержащие указатели) потеряют область действия и вызовут их деструкторы.

Никакой контейнер STL никогда не позвонит delete для вас, насколько я знаю. Если вы выделяете и передаете указатель, вам необходимо освободить его.

5

Метод clear действительно вызовет деструкторы. Тем не менее, ваш вектор хранит указатели, а деструктор для указателей - тривиальный no-op. Это не звонок delete.

Таким образом, просто позвоните clear и не освободите память для всех int объектов, которые были выделены с помощью new. Вам нужно delete им.

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

+0

ОК. Поэтому, если я заменил вектор на это: «vector > Vector;" Мне не придется использовать какие-либо методы? – DeadCapacitor

+1

НЕТ! Не используйте 'auto_ptr' в контейнерах. Они не соответствуют требованиям семантики копии для контейнеров. Вам нужно использовать что-то вроде 'shared_ptr' из Boost, tr1 или C++ 0x –

+0

.' Shared_ptr' было бы лучше; 'auto_ptr' не отвечает всем требованиям к вещам, которые могут храниться в контейнерах STL. –

0

Если вы используете vactor<int *>, то у вас будет вектор указателей, и вам придется выделять память для каждого элемента и самостоятельно освобождать эту память. Не имеет смысла использовать вектор указателей, если размер типа, который вы хотите сохранить в векторе, довольно большой.

На самом деле, когда вы делаете vector<T>::push_back(val) он собирается хранить копию val с помощью конструктора копирования T::T(T &orig) и вызвать деструктор для всех элементов, когда вы делаете clear()

+1

Хранение больших объектов - не очень хорошая причина для использования указателей. Тем более, что все хорошие компиляторы теперь поддерживают ссылки rvalue. –

+0

Я не сказал, что это хорошая причина, но в некоторых случаях это может быть полезно. – Elalfer

1

Как ответили другие, вектор делает вызывать деструктор каждого элемента , В вашем случае элементы являются указателями и, следовательно, не освобождают память. Для вашего приложения лучшим выбором является использование интеллектуального указателя ссылок, например boost: shared_ptr. Когда больше нет ссылок на элементы (например, написанный вами пример), память будет автоматически освобождена.

PS: Не используйте интеллектуальный указатель «без ссылки», такой как std :: auto_ptr с вектором.