012
11.11.2005, 22:34 Uhr
Spacelord
Hoffnungsloser Fall
|
Wenn der vector seine Grösse anpasst kopiert er die Elemente in den neu belegten Speicherplatz und löscht dann die alten Elemente.Dabei wird vector-intern der Destruktor von Konto "benutzt". Spring mal mit den Debugger in der push_back Codezeile rein. Ich denke der Code wird dir noch nicht allzuviel sagen aber der entscheidene Part ist dieser hier:
C++: |
template<typename _Tp, typename _Alloc> void vector<_Tp,_Alloc>:: _M_insert_aux(iterator __position, const _Tp& __x) { if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { std::_Construct(this->_M_impl._M_finish, *(this->_M_impl._M_finish - 1)); ++this->_M_impl._M_finish; _Tp __x_copy = __x; std::copy_backward(__position, iterator(this->_M_impl._M_finish-2), iterator(this->_M_impl._M_finish-1)); *__position = __x_copy; } else { const size_type __old_size = size(); const size_type __len = __old_size != 0 ? 2 * __old_size : 1;//Hier wird die neue Groesse des vectors festgelegt(verdoppelt) iterator __new_start(this->_M_allocate(__len)); iterator __new_finish(__new_start); try { __new_finish = std::uninitialized_copy(iterator(this->_M_impl._M_start), __position, __new_start); std::_Construct(__new_finish.base(), __x); ++__new_finish; __new_finish = std::uninitialized_copy(__position, iterator(this->_M_impl._M_finish), __new_finish); } catch(...) { std::_Destroy(__new_start,__new_finish); _M_deallocate(__new_start.base(),__len); __throw_exception_again; } std::_Destroy(begin(), end()); //Hier kommen deine Destruktor Aufrufe her! _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage - this->_M_impl._M_start); this->_M_impl._M_start = __new_start.base(); this->_M_impl._M_finish = __new_finish.base(); this->_M_impl._M_end_of_storage = __new_start.base() + __len; } }
|
In dem Beispiel mit den 3 Elementen fängt meine Testversion mit ner Grösse von 0 an. Dann kommt diese Codepassage:
C++: |
const size_type __len = __old_size != 0 ? 2 * __old_size : 1;//
|
Hier wird die neue Grösse auf 1 festgelegt.Weil es noch keine Elemente zu löschen gibt,gibt es auch keinen Destruktoraufruf. Beim nächsten Durchlauf muss der vector wieder vergrössert werden. An der gleichen Stelle wird die neue Grösse jetzt auf 2 festgelegt. Das eine Element das im vector ist wird in den neuen Speicherbereich kopiert und der alte Speicherbereich wird "freigegeben",wobei der Destruktor des Elements aufgerufen wird.Dann wird das zweite Element in den vector gespeichert. Beim nächsten Durchlauf wird der vector wieder vergrössert.Diesmal auf 4->die beiden Elemente werden kopiert und dann zerstört-> wieder 2 Destruktoraufrufe. Dann folgen noch 3 Destruktoraufrufe wenn die Ausführung den Sichtbarkeitsbereich des vectors verlässt.Der vector ist eine Autovariable und wird zerstört.Dabei sorgt der vector dafür dass alle seine Elemente ordnungsgemäss zerstört werden. Ich komm da also auf 6 Destruktoraufrufe. Warum du 9 hast musst du mal mit dem Debugger selber untersuchen,aber es wird da vom Prinzip her das Gleiche passieren.Warscheinlich nur irgendwie anders implementiert.
Was die Speicherlöcher angeht. Speicher den du mit new besorgt hast musst du mit delete wieder freigeben! In dem Augenblick wo du den Block der Schleife,in der du mit new das Objekt erstellst, verlässt verlierst du den Zeiger auf den Speicherbereich und damit jede Chance den Speicher wieder mit delete freizugeben.Also solltest du entweder das Objekt freigeben nachdem du das Objekt mit push_back in den Vector gesetzt hast(das geht weil der vector ne Kopie macht),oder du speicherst gleich den Kontozeiger im vector und gibst sobald du den vector nicht mehr benötigst mit delete sämtliche Speicherbereiche wieder frei.
MfG Spacelord -- .....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes. |