'I have a vector of pointers to objects. How to free memory?

For example:

class Airport : public vector<Airline*>

How do I free the memory properly? I would prefer not use smart pointers as I have not learned it yet in my course.

c++


Solution 1:[1]

As others have pointed out, Airport should not inherit from vector. Airport should contain a vector. Then there is the question of who owns the Airlines, do you want the Airlines to be destroyed when the Airport is destroyed? If so I suggest either a simple std::vector<Airline>:

class Airport {
    std::vector<Airline> airlines_;
    //...
};

Or if you need polymorphism, i.e Airline is a base class with specializations for different Airlines I suggest smart pointers:

class Airport {
    std::vector<std::unique_ptr<Airline>> airlines_; 
    //...
};

If you really don't want to use smart pointers you could use raw pointers and then carefully delete them in the destructor:

class Airport {
    std::vector<Airline*> airlines_;
  public:
    Airport(const Airport&) = delete;             // not allowed
    Airport& operator=(const Airport&); = delete; // not allowed
   ~Airport() { 
        for (auto airline : airlines) {
            delete airline;
        }
    }
   //...
};

If you do this you need to think carefully about what copying behaviour you want Airport to have because the default copy constructor and assignment operator will not manage the memory properly. As a first step you can prevent copying by 'delete'ing copy constructor and assignment operator as I have above. But I suggest as soon as you learn about smart pointers use them instead as most of these problems go away.

If the Airport does not own the Airlines then store raw pointers or shared smart pointers in the vector and leave it to whoever owns the Airlines to free the memory properly. In my mind an Airline can operate in more than one Airport so it doesn't make sense for the Airport to own the Airline so there should be a separate container of Airline but it depends on your model.

Solution 2:[2]

class Airport : public vector<Airline*>

A vector doesn't have a virtual destructor, so inheriting from it lands you into UB behavior.

Try this instead:

class Airport
{
    std::vector<std::unique_ptr<Airline>> airlines_; // notice std::unique_ptr
    // ...
};

By storing std::unique_ptr instead of raw pointers, you will not have to delete anything explicitly. If (for some reason) you need to store raw pointers, the deleting of the pointers should be done like this:

Airport::~Airport() { // declare it in the class
    std::for_each(airlines_.begin(), airlines_.end(),
        std::default_delete<Airline>{});
}

Solution 3:[3]

To start: inheriting from std::vector is wrong for technical reasons (it does not have a virtual destructor). In your case it also seems wrong for domain reasons: an Airport is not a Sequence of Airlines. Just imagine someone explaining AirportS to you in the real world using those words. You would certainly argue the point.

You have two approaches.

Use values (std::vector<Airline>) to circumvent this problem. You also should define a proper equality operator operator==(const Airline&, const Airline&) if you do this.

or

If AirportS are really supposed to store pointers to AirlineS, you need to be aware of ownership. Does an Airport really own the AirlineS stored in it? If so, it should delete them at the end of its life-time. If not, they should life on. In the first case, someone else needs to take care of storing and destroying AirlineS.

If an Airport owns and destroys AirlineS you need to make sure you observe the Rule of Three in your implementation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 utnapistim
Solution 3 pmr