Search code examples
c++c++17fold-expression

variadic template function (to delete number of dynamically allocated variables)


I don't get exactly if I am doing the right thing

template<typename ...AllVArgs>
auto dealloc_all(AllVArgs &..._AllVArgs) -> void {
 (((std::cout << "\nin dealloc_all function " << &_AllVArgs), ...) << " ");

 ((delete _AllVArgs), ...);
 ((_AllVArgs), ...) = nullptr;
}

I allocated 2 struct and try to free them by using the variadic template function

struct a {
 int x;
}
a *v1 = new a();
a *v2 = new a();

std::cout << "\nin a function " << &v1<< " " << &v2;
//address output = 0x1dce9ff588 0x1dce9ff580

dealloc_all(v1, v2);

I just wanted to know if I successfully free the allocated memory. btw these are the output it gives me, and I think there's no problem with it?

in a function 0xa4b89ff5c8 0xa4b89ff5c0
in dealloc_all function 0xa4b89ff5c8   
in dealloc_all function 0xa4b89ff5c0 

Solution

  • just wanted to know if I successfully free the allocated memory.

    Yes: with

    ((delete _AllVArgs), ...);
    

    you correctly free all the allocated memory

    I don't get exactly if I am doing the right thing

    Not completely: with

    ((_AllVArgs), ...) = nullptr;
    

    you set to null pointer only the last argument of your function. If you want to set to null pointer all arguments, you have to rewrite your folding as follows

    ((_AllVArgs = nullptr), ...);
    

    To verify what I say, I've rewritten your code as follows

    #include <vector>
    #include <iostream>
    
    struct a
    { ~a() { std::cout << "deleting a" << std::endl; } };
    
    template <typename ... Args>
    auto dealloc_all (Args & ... as)
    {
      std::cout << "before delete" << std::endl;
    
      ((delete as), ...);
    
      std::cout << "after delete" << std::endl;
    
      ((as), ...) = nullptr;
    }
    
    
    int main()
    {
      a *v1 = new a();
      a *v2 = new a();
    
      std::cout << "\nbefore function " << v1<< " " << v2 << std::endl;
    
      dealloc_all(v1, v2);
    
      std::cout << "\nafter function " << v1<< " " << v2 << std::endl;
    }
    

    so you can see that "deleting a" is written two times between "before delete" and "after delete"; so the destructor (called when you delete an allocated object) is called for every as... object.

    But you can also see something as

     after function 0x55b20b759eb0 0
    

    printing the values of v1 and v2 (observe: I print the values of the pointers, not the addresses); if you want

     after function 0 0
    

    you have to change

     ((as), ...) = nullptr;
    

    to

     ((as = nullptr), ...);