Новый оператор с векторами - PullRequest
4 голосов
/ 26 января 2011

Эти вопросы относительно просты. При использовании векторов, должен ли я использовать оператор 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?

Ответы [ 6 ]

5 голосов
/ 26 января 2011

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

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

5 голосов
/ 26 января 2011

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

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

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

2 голосов
/ 26 января 2011

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

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

2 голосов
/ 26 января 2011

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

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

1 голос
/ 26 января 2011

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

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

0 голосов
/ 26 января 2011

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

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

...