Search code examples
c++sfmldynamic-memory-allocation

Saving a pointer to heap created in the local area


I made a "Planet" class and am trying to initialize a vector array based on this class in the client file of my project.

bool addPlanet(std::vector<Planet>& planets, std::string filePath)
{
    std::ifstream infile(filePath, std::ios_base::in);
 
    if (infile.fail()) {
        // File could not be opened
        return false;
    }
 
    std::string planetName, imagePath;
    float posX, posY, rotationZ, scaleX, scaleY;
    unsigned long long int planetMass;
 
    while (infile >> planetName >> posX >> posY >> rotationZ >> scaleX >> scaleY >> planetMass >> imagePath)
    {
        Planet* newPlanet = new Planet(sf::Vector2f(posX, posY), rotationZ, sf::Vector2f(scaleX, scaleY), planetMass, imagePath);
        
        planets.push_back(*newPlanet);
    }
 
    infile.close();
 
    return true;
}

But I can't figure out if the following piece of code is causing a memory leak:

while (infile >> planetName >> posX >> posY >> rotationZ >> scaleX >> scaleY >> planetMass >> imagePath)
{
    Planet* newPlanet = new Planet(sf::Vector2f(posX, posY), rotationZ, sf::Vector2f(scaleX, scaleY), planetMass, imagePath);
        
    planets.push_back(*newPlanet);
}

I think about it like this:

I allocate dynamic memory for a new instance of the "Planet" class. Using the push_back method — the vector 's internal iterator becomes a second pointer to the new instance. And when we exit the loop, there is still a pointer to the newly allocated heap in vector .

Do I understand everything correctly or am I just bad at reading the documentation?


Solution

  • Your code creates a Planet object:

    Planet* newPlanet = new Planet(sf::Vector2f(posX, posY), rotationZ, sf::Vector2f(scaleX, scaleY), planetMass, imagePath);
    

    Then, it copies this object into the vector:

    planets.push_back(*newPlanet);
    

    But it doesn't release the memory corresponding to the original object. The vector only owns the copy, not the original Planet object.


    You can simply solve this issue but not using new at all:

    Planet newPlanet(sf::Vector2f(posX, posY), rotationZ, sf::Vector2f(scaleX, scaleY), planetMass, imagePath);
    planets.push_back(std::move(newPlanet));
    

    Here, it is the code block the one who owns the newPlanet object.

    However, you may want to directly use std::vector::emplace_back() instead of new and push_back():

    planets.emplace_back(sf::Vector2f(posX, posY), rotationZ, sf::Vector2f(scaleX, scaleY), planetMass, imagePath);
    

    This way, the vector acquires the ownership of the single Planet object that is created.