Home > other >  How to implement a destructor
How to implement a destructor

Time:06-05

I am having trouble to understand vector and heap. So far, I want to create a vector of int. The element of this vector should be stored in the heap. I have implemented a class, but I don't think that I have implement the destructor correctly. There is also a problem with the move constructor. If I want to move vector a to vector b, a stays with the same values.

Class A {
private : 
vector<int> myV ;
int val; 
size_t Size; 
public: 
    A(){
    myV.resize(0);      
this->value = 0 ;
   }

A(size_t size){
    MyVector.resize(0);
    Size = size ;
    this->value = 0 ;
}

A(size_t size, int value){
    A.resize(0);
    Size = size;
    Val = value;
    MyVector.push_back(Val);
}
~A()
{
     myV.clear();
     delete &myV;
}
    A(A&&other)
{
    *this = std::move(other);
    this->myV = other.myV ;
}

I tried to check the code, But

int main()
{
    Vector myVect(2,5);
    Vector m (std::move(myVect));
    std::cout<<m[0]<<std::endl;
}

values of myVect is not moved, though it stayed as they are.

From what I understood that vector should allocate the element on the heap, how can I release it where there isn't memory leak.

CodePudding user response:

You should read about the rule of 0 (eg here, it starts with rule of 3/5, make sure to read till the end).

std::vector already manages the memory for you. You also should not implement a move constructor when it does nothing more than the compiler generated one can do. Moreover you should use the member initialzer list to initialize members. Though a default constructed std::vector is already of size 0, no need to resize it. And you forgot to initialize Size in the default constructor, its also not moved in the move constructor. I suppose Size should be the size of the vector, but the vector already keeps track of its size, so I removed that member. I further suppose that val is some value you want to store in the vector, so there is no need to have it duplicate as member.

Your class can look like this:

class A {
    std::vector<int> myV ;
public: 
    A() = default;
    A(size_t size) : myV(size) {}    
    A(size_t size, int value) : myV(size,value) {}
    std::vector<int> get() { return myV; }
};

CodePudding user response:

Please find below a working example.

#include <vector>
#include <iostream> // Debug only

class Vector
{
    private:
        std::vector<int> _myVec;
        int _val;
        size_t _size;

    public:
        // "Regular" Construtors
        Vector() : _val(0), _size(0) {}
        Vector(size_t size) : _size(size), _val(0) {}

        Vector(size_t size, int value) : _val(value), _size(size)
        {
            _myVec.push_back(_val);
        }

        // Move Constructor
        Vector(Vector&& other)
        {
            std::cout << "Move Constructor called\n"; // Debug purpose

            _myVec = std::move(other._myVec);
            _val = std::move(other._val);
            _size = std::move(other._size);
        }

        // Destructor
        ~Vector()
        {
            _myVec.clear(); // useless being given the destructor will destroy the vector of int anyway
        }

        // Getter
        std::vector<int> getMyVec() const { return _myVec; }
};

int main()
{
    std::cout << "Hello world\n";

    Vector _myVecect(2, 5);
    Vector m(std::move(_myVecect));

    std::cout << m.getMyVec()[0] << std::endl;

    return 0;
}

When you create a move constructor, you have to move every members of the class, like it is done above ^. For your cout line in your main, this can't work like because your variable 'm' is an instance of your class Vector. You cannot manipulate it through the [] operator unless you define it yourself to work with it like it is an array.

You don't need this kind of destructor doing this being given you do not manage streams or dynamic memory. If you have a stream, the destructor would be a good place to close to ensure no one will try to use the stream after the object deletion. In the case of dynamic memory, you would not have to use delete here because we now have in modern C smart pointers (unique_ptr and smart_ptr that do the job for you).

  • Related