Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

explicit destructor

Tags:

c++

destructor

The following code is just used to illustrate my question.

template<class T>
class array<T>
{
 public:
    // constructor
    array(cap = 10):capacity(cap)
    {element = new T [capacity]; size =0;}

    // destructor
    ~array(){delete [] element;}
    void erase(int i);
    private:
      T *element;
      int capacity;
      int size;
};



template<class T>
void class array<T>::erase(int i){
     // copy
     // destruct object
    element[i].~T();  ////
    // other codes
} 

If I have array<string> arr in main.cpp. When I use erase(5), the object of element[5] is destroyed but the space of element[5] will not be deallocated, can I just use element[5] = "abc" to put a new value here? or should I have to use placement new to put new value in the space of element [5]?

When program ends, the arr<string> will call its own destructor which also calls delete [] element. So the destructor of string will run to destroy the object first and then free the space. But since I have explicitly destruct the element[5], does that matter the destructor (which is called by the arr's destuctor) run twice to destruct element[5]? I know the space can not be deallocated twice, how about the object? I made some tests and found it seems fine if I just destruct object twice instead of deallocating space twice.

Update

The answers are:

(1)I have to use placement new if I explicitly call destructor.

(2) repeatedly destructing object is defined as undefined behavior which may be accepted in most systems but should try to avoid this practice.

like image 796
Sean Avatar asked Jan 21 '23 14:01

Sean


1 Answers

You need to use the placement-new syntax:

new (element + 5) string("abc");

It would be incorrect to say element[5] = "abc"; this would invoke operator= on element[5], which is not a valid object, yielding undefined behavior.

When program ends, the arr<string> will call its own destructor which also calls delete [] element.

This is wrong: you are going to end up calling the destructor for objects whose destructors have already been called (e.g., elements[5] in the aforementioned example). This also yields undefined behavior.

Consider using the std::allocator and its interface. It allows you easily to separate allocation from construction. It is used by the C++ Standard Library containers.

like image 185
James McNellis Avatar answered Jan 31 '23 23:01

James McNellis