0

I've a big function which allocates 2 arrays in the heap memory and returns many times in many different places. I would like to make the function call delete[] for my 2 arrays whenever she returns, without having to write delete[]s before each return.

int function(int a)
{
    size_t heap_arr1_len{100};
    int* heap_arr1{new int[heap_arr1_len]};
    
    size_t heap_arr2_len{200}; 
    int* heap_arr2{new int[heap_arr2_len]};
    
    //I was thinking of something similar to:
    struct at_return{
        ~at_return()
        {
        delete[] heap_arr1;
        delete[] heap_arr2;
        }
    } at_return;

    /*...............
    .................
    ......return 0;*/
    /*...............
    .....return 10;*/
    //ecc.
}

but with a compilation-time error i've figured out that a struct can't access the local variables of the function which is contained in.

What would you do in order to avoid to having to write delete[] heap_arr1;, delete[] heap_arr2; each time before each return?

thomas
  • 111
  • 8
  • 9
    Use a `std::vector` instead. It will clean up after itself. [RAII](https://en.cppreference.com/w/cpp/language/raii) is one of C++'s best features. – NathanOliver May 02 '22 at 21:33
  • Use a `std::vector` instead. You could also use a class as a scope guard to cleanup in its destructor,. – Retired Ninja May 02 '22 at 21:34
  • If you don't want to use the std, you can create a simple wrapper for your array, which will handle construction and deletion in ctor and dtor. – Adrien Givry May 02 '22 at 21:34
  • 1
    @AdrienGivry: WHY?? `std::vector` does exactly that! – TonyK May 02 '22 at 21:40
  • @TonyK: "if you don't want to use the std" – Adrien Givry May 02 '22 at 21:42
  • 1
    @AdrienGivry: That's like saying "If you don't want to use `C++`, you can just program it in assembly language." – TonyK May 02 '22 at 21:44
  • 2
    By the way, this is one of the use cases for `goto` (in `C` at least). – TonyK May 02 '22 at 21:45
  • i've written some functions that deal with binary files to / from arrays. i can't use vectors. when i'll learn how to do the same with vectors, i'll use them, but for now i just want to go ahead with arrays – thomas May 02 '22 at 21:48
  • There is also std::array if you don't want to use a vector. Or use std::unique_ptr. – user18533375 May 02 '22 at 21:52
  • 4
    The proper way of doing this without a `std::vector` is harder than learning how to use `std::vector`. :) It's like saying *"I don't know how to use my left hand yet, so for now I want to do push-ups with a single hand"*. – HolyBlackCat May 02 '22 at 21:53
  • Isn't this literally what `try..finally` blocks were invented for? – 500 - Internal Server Error May 02 '22 at 21:59
  • 5
    @500-InternalServerError There is no `try..finally` in C++. You may have confused it with C# or Java or JavaScript. The C++ version of` finally` is RAII. – Raymond Chen May 02 '22 at 22:15
  • _I've a big function_ Can you see a way to split it up? From what you say, it's already proving to be a maintenance headache, and it may well do so again some time down the line. – Paul Sanders May 02 '22 at 23:35

3 Answers3

4

Don't allocate memory manually using new, use std::vector instead:

size_t heap_arr1_len = 100;
std::vector<int> heap_arr1(heap_arr1_len);

Then you don't need to worry about delete.


But using a destructor like this is in fact a great idea, assuming no suitable wrapper class exists. This trick is known as a scope guard. And here's a working implementation.

It could be useful e.g. when dealing with C libraries, which can't provide classes with destructors. You could write a reusable wrapper class with a destructor, or you could use a scope guard as an ad-hoc solution.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
3
#include <memory>

int function(int a)
{
    size_t heap_arr1_len{100};
    std::unique_ptr<int[]> heap_arr1{new int[heap_arr1_len]};

    // Etc
}

If you need the underlying pointer for your file reading/writing functions, use heap_arr1.get().

user18533375
  • 175
  • 1
  • 3
    This also has the benefit of freeing the memory if an exception is thrown, which the manual `delete[]` does not handle. – Raymond Chen May 02 '22 at 22:14
  • 1
    I prefer `std::make_unique`, to have a no-brainer strict rule of never calling `new`/`delete` manually (outside of custom containers/smart pointers). – HolyBlackCat May 02 '22 at 22:20
0

I use a can_continue method so there is only one entry and one exit (MISRA rule).
First set a Boolean variable:

bool can_continue = true;

The pattern then becomes:

if (can_continue)
{
   // do some work
   // set can_continue to false to return unexpectedly
}

It may not be the fastest code, but it meets the criteria for one entry and one exit.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154