Reputation: 8778
In chapter 11 of Accelerated C++, the authors present a Vector class emulating the behaviour of std::vector using arrays. They use the allocator class to handle memory management. The role of the uncreate
function is to destroy each element of the array and deallocate the space allocated for the array:
template <class T> void Vec<T>::uncreate() {
if (data) {
// destroy (in reverse order) the elements that were constructed
iterator it = avail;
while (it != data)
alloc.destroy(--it);
// return all the space that was allocated
alloc.deallocate(data, limit - data);
}
// reset pointers to indicate that the Vec is empty again
data = limit = avail = 0;
}
Obviously we need to deallocate allocated space. But it's unclear to me why we need to destroy individual elements as well. What would happen if we only deallocated memory without destroying individual elements?
Upvotes: 11
Views: 3305
Reputation: 55395
The reason is that it'd might get you in trouble. The paragraph 4 from chapter 3.8 (Object lifetime) of C++standard explains why (emphasis mine):
A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
It means it's fine to do it on memory that's occupied by objects with trivial destructor(*) or objects that don't have one at all (such as ints
and the like). But when the memory contains objects of a class that needs to do some work in the destructor (like closing network connections or files, flushing buffers, releasing memory), you'll leak resources (and formaly by the standard, invoke undefined behaviour).
(*) A destructor is trivial if it's compiler generated, is not virtual, and all the non-static members and direct base classes of the class it is member of have trivial destructors.
Upvotes: 14
Reputation: 2713
Destroying the individual elements ensures that their destructors are called and therefore they have a chance to free any resources they own. Simply deallocating the memory would not call the destructor of the object placed in that memory.
Upvotes: 10