0

Here's part of a function:

std::queue<std::string>* shunting_yard(std::vector<std::string> input){
    std::queue<std::string>* output = new std::queue<std::string>();
    ...
    return output;

I've dynamically allocated queue output is pointing to on the heap. However, when I try to free/delete the queue in int main() I get an error because output is declared out of scope.

Considering the fact that I'm returning output in the above function- so I can't free it inside the function- how can I make sure that there is not a memory leak? One potential solution I've thought of would be declaring std::queue<std::string>* output in the global scope and output = new std::queue<std::string>() inside the function, but are there any other solutions to this out of scope error?

rjc810
  • 425
  • 1
  • 3
  • 17
  • 3
    `std::unique_ptr`. But there isn't really a reason to dynamically allocate an `std::queue`, as its storage itself is, in turn, dynamically allocated. Just return the value. – Quentin Jul 19 '21 at 17:24
  • @Quentin I decided to return a pointer to it because I wanted to check if it was a NULL pointer (in case anything went wrong inside the function). Is this a valid reason? – rjc810 Jul 19 '21 at 17:26
  • No. If something goes wrong and the function cannot return a sensible result, throw an exception. – Quentin Jul 19 '21 at 17:27
  • 1
    And if exception doesn't make sense (as in the failure to produce a good result is not an exceptional event) use [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional). You could also return a `std::pair` of `std::queue` and `bool`. Set the `bool` to `true` if the result is acceptable. – user4581301 Jul 19 '21 at 17:30
  • 1
    Generalization: [Why should C++ programmers minimize use of 'new'?](https://stackoverflow.com/questions/6500313/why-should-c-programmers-minimize-use-of-new) – user4581301 Jul 19 '21 at 17:32

1 Answers1

4

You do not delete variables, or pointers. You delete things you allocate with new. The line:

std::queue<std::string>* output = new std::queue<std::string>();

does not allocate a variable called output with new. It allocates a queue, which has no name, and creates a local variable called output, and stores the address of the queue into the local variable output.

This line:

return output;

returns the address of the queue. Because it also ends the function, the local variable output is destroyed (just like all local variables). The caller receives the address.

How do you call this function? You didn't show that code, but it's something like:

std::queue<std::string>* woof = shunting_yard(meow);

In this case, this creates a new local variable in the caller, called woof, which now holds the address of the queue that shunting_yard created.

You can delete the queue by passing its address to delete. Its address is stored in the variable woof. So you can write delete woof;. The fact that the address was stored in a different variable is irrelevant, as long as the address is the same.


More advanced programmers will use std::unique_ptr<std::queue<std::string>>. But I recommend learning to do new and delete by hand first, before learning unique_ptr, so that you'll understand what unique_ptr actually does.

Really advanced programmers will realize they don't new at all, and just use std::queue<std::string> (no pointer).

user253751
  • 57,427
  • 7
  • 48
  • 90