1

Having this class:

template<class T>
class Vec
{
public:
    typedef T* iterator;
    typedef T* const const_iterator;
    typedef T value_type;

    Vec() {
        create();
    }
    explicit Vec(size_t n, const T& val = T()) {
        create(n, val);
    }
    void clear() //here, I cannnot destroy nither by alloc.destroy, nor i->~T()
    {
        if (data)
        {
            iterator i = avail;
            while (i != data)
            {
                alloc.destroy(--i); //or i->~T()
            }
        }
        avail = data;
    }
    ...
private:
    iterator data;
    iterator avail;
    iterator limit;

    std::allocator<T> alloc;
    void create();
    void create(size_t n, const T &val);
    ...

Now I will use the clear functino (version of std::allocator<T>::destroy, not destructor) in main file:

#include "vec2.hpp"
#include <iostream>
#include <string>

using namespace std;

int main()
{
    Vec<string> v(3, "abc");
    v.clear();
    cout << v[2] << endl;
}

1.) Now even I have cleared the Vec class (performing destructor for all elements in it), I can still output v[2] -> "abc" even thought the string should perform the destructor and thus be empty string.

2.) should I use alloc.destroy(i), where the i is T*, or should I use i->~T()?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • 2
    Destroying an object means you are not allowed to look at it afterwards. There is no reason, for example, for the implementation to bother writing a bunch of `0`s into that memory, so often that memory address will still contain the same data as before. That doesn't mean you are allowed to look at it though. This is called [Undefined Behaviour](https://en.wikipedia.org/wiki/Undefined_behavior). – BoBTFish Aug 10 '20 at 14:45
  • And does `destroy` equal `destruct` ? – milanHrabos Aug 10 '20 at 14:46
  • 1
    "the string should perform the destructor and thus be empty string" is a false conclusion. The correct one is: "and thus I am not allowed to use it anymore, this is UB". – freakish Aug 10 '20 at 14:47
  • @freakish what is then `std::string::~string()` suppose to do then? – milanHrabos Aug 10 '20 at 14:47
  • We can see [here](https://en.cppreference.com/w/cpp/memory/allocator/destroy) that calling `allocator::destroy()` is basically the same as calling the destructor on the pointed-to object. – BoBTFish Aug 10 '20 at 14:48
  • @milanHrabos nothing? Something? Who cares as long as it destroys the object and frees memory? – freakish Aug 10 '20 at 14:48
  • @BoBTFish, ok so what should I choose then, in my case? – milanHrabos Aug 10 '20 at 14:48
  • @freakish I do because every class, or non-POD has specific destructors, so does `std::string` – milanHrabos Aug 10 '20 at 14:49
  • @milanHrabos Hard to say without sitting down and going over the design of the whole component with you to be honest. I would say, if you want to support allocators, do it completely and correctly. That is surprisingly hard, so if this is just a learning exercise, I'd suggest not trying to use allocators at all. – BoBTFish Aug 10 '20 at 14:50
  • 1
    @milanHrabos consider this: you have a string. Why would you ever "clear" the string on destruction? What purpose that this cleaning serve? It only wastes instructions. The same space can be reused later. And this happens all the time, people design stuff to be as efficient as possible. But this is an irrelevant implementation detail. What is relevant is that you are not allowed to access memory after deallocation. – freakish Aug 10 '20 at 14:50
  • 2
    This *very good* answer is closely related: https://stackoverflow.com/a/6445794/5910058 – Jesper Juhl Aug 10 '20 at 14:53
  • `allocator::destroy` has been obsoleted in C++17 and removed in C++20 (for a good reason!). There is no reason to ever call it in new programs. – SergeyA Aug 10 '20 at 15:04

0 Answers0