Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I assume an object's destructor is called immediately after removal from STL containers?

Consider the following code:

class T { ... }; // T has a non-trivial destructor

void foo() {
    std::vector<T> v( 5 );
    v.pop_back();

    ...
}

After v.pop_back(), does the STL guarantee that T::~T() has been called for v.back()? Note: The question holds for any method of vector that removes elements (e.g. resize(), erase(), etc...)

I am writing container classes for my application and I would like them to conform as much as possible to the principles used by the standard library. If my container class does not make this guarantee, are there any risks?

like image 512
MarkB Avatar asked Jan 23 '14 17:01

MarkB


2 Answers

C++11 § 23.2.3 describes the requirements for a sequence container.

The entry for pop_back() says it "Destroys the last element."

I suppose you could argue that it doesn't explicitly say immediately. Though, I suspect that was meant to be implied.

Another requirement of note is in § 23.2.1. It says about a container's destructor

note: the destructor is applied to every element of a; all the memory is deallocated.

So I suppose you could defer destroying the removed elements so long as they're destroyed before the container is destroyed.

That all said if you're truly trying to follow the principles of the standard I can confidently say the standard authors would have expected a removed element to be immediately destroyed.

like image 158
deft_code Avatar answered Oct 05 '22 15:10

deft_code


std::vector::erase

Removes from the vector container and calls destructor on element. The same applies to std::vector::pop_back.

void pop_back() {
    --this->_M_impl._M_finish;
    this->_M_impl.destroy(this->_M_impl._M_finish);
      }

and destroy is a method of allocator:

void destroy(pointer __p) { __p->~_Tp(); }
                              ^^^
                            dereference and call destructor
                            on new_allocator::value_type

on my implementation allocator for vector which is template argument Alloc = std::allocator<_Tp> initializes it's base __glibcxx_base_allocator whith new_allocator due to this definition:

 #define __glibcxx_base_allocator  __gnu_cxx::new_allocator 

allocator(const allocator& __a) throw()
      : __glibcxx_base_allocator<_Tp>(__a) { }
like image 27
4pie0 Avatar answered Oct 05 '22 16:10

4pie0