I wouldn't use the notation with double pointers. It is sure to result in a memory leak somewhere since it is not clear who will cleanup the memory. In C++ I would use one of the following methods (using either std::array, or std::vector). Which is also more in line with the C++ core guidelines regarding the use of new/delete (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines look for anything about pointers and/or new/delete)
#include <array>
#include <vector>
struct fruit
{
};
// sizes know at compile time then use a function template
template<std::size_t N, std::size_t M>
auto func2create()
{
// create initialized array
std::array<std::array<fruit, M>, N> fruits{};
return fruits;
}
// for runtime sizes use std::vector
// note I don't use ints (they can have negative values
// I don't want to test for that)
auto func2create(const std::size_t n, const std::size_t m)
{
// create n rows of m fruits
std::vector<std::vector<fruit>> fruits(n, std::vector<fruit>(m));
return fruits;
}
int main()
{
// compile time allocate fruits
{
auto fruits = func2create<4, 4>();
auto fruit = fruits[1][1];
}
// runtime alloacted fruits
{
auto fruits = func2create(4ul, 4ul);
auto fruit = fruits[1][1];
}
return 0;
}
newanddelete(or writing a custom container or smart pointer), you shouldn't use them at all. Returning a 1Dstd::vectorwould make your life a lot easier.newanddelete(this is not my choice tho).int foo() {int x = 42; return x;}. How do you use (the copy of)xoutside of the function? By writing something likeint y = foo();, then usingy. And here, you dofruit **a = func2create(10, 20);, then useainstead ofarr.funcDel(**arr)and passing**ato it, will be viewed as good solution.