0
int ** foo()
{
    int ** multiArray = new int*[3];

    int one[3] = { 1, 2, 3 };
    int two[3] = { 4, 5, 6 };
    int three[3] = { 7, 8, 9 };

    multiArray[0] = one;
    multiArray[1] = two;
    multiArray[2] = three;

    return multiArray;
}

Returning multiArray works outside of the above function, but I have reserves about the the way the inner arrows (one, two, three) are allocated. My first reaction is that they are allocated on the stack, not the heap. I would want the heap. Even though they somehow work for me outside of that function, when I try to delete them as I should, it fails.

If I do something such as:

int ** allocatedMultiArray = foo();
int test = allocatedMultiArray[0][2]; // We get 3! Success!
for (int i = 0; i < 8; ++i)
{
     delete[] allocatedMultiArray[i]; // FAILS!
}
delete[] allocatedMultiArray; // WORKS! (If we skip the above for loop of course)

I was reading this page on multi-dimensional array and he specifically had to the above for loop to deallocate a 2D array (or an additional loop for a 3D array). But, back in my equivalent of foo(), he manually allocated the array to the heap with the new operator with a loop as opposed to { 1, 2, 3 } initializing an array then assigning it like I did. http://www.cplusplus.com/forum/articles/7459/

So if I skip the for loop that fails, am I leaking memory? Is what I am doing should even work? I really don't want to loop over the multiArray, call new on each index, then manually assign each int. This is just a simplified { 1, 2, 3 } but I have a somewhat more complex number set obtained from different functions that reads much better with the { } notation.

EDIT: The failure on that inner delete is:

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

EDIT2: So if it is undefined behavior and the one, two, three arrays are not allocated on the heap as I initially believed, then how does one do something like the following:

int ** foo()
{
    int ** multiArray = new int*[3];
    for(int i = 0; i < 3; ++i)
    {
        multiArray[i] = new int[3];
    }
    multiArray[0] = { 1, 2, 3 }; // Fail "Too many initializer values" on 2
    multiArray[1] = { 4, 5, 6 }; // Fail
    multiArray[2] = { 7, 8, 9 }; // Fail

    return multiArray;
}

EDIT 3: Not a duplicate as I was specifically asking for a different answer than the ones provided on the question, as well as the fact that I was trying to identify if the arrays were being done on the heap or stack. Neither of which are addressed in the question marked as a duplicate. In fact, I specifically addressed the most upvoted answer of that question saying that it was insufficient.

user99999991
  • 1,351
  • 3
  • 19
  • 43
  • 3
    The code doesn't really work. It seems to work, but it invokes *undefined behaviour* This is because you return pointers to local variables. – juanchopanza Sep 15 '14 at 21:40
  • `one`, `two`, and `three` are also going to have to be allocated on the heap, but you're allocating them on the stack. When `foo` returns, they cease to exist and they will likely be overwritten by other things. Doing what you're doing just to avoid some trivial initialization is silly. Just allocate those arrays with `new` and initialize them. It's no big deal. – Carey Gregory Sep 15 '14 at 21:43
  • As I thought :( But then how does one allocate and initialize with the { } notation. Is there a way? – user99999991 Sep 15 '14 at 21:47
  • 3
    `multiArray[0] = new int[3] { 1, 2, 3 };` etc. – T.C. Sep 15 '14 at 21:57
  • Please do answer so I can give credit to someone for something. Preferably if you answer with both the facts of the original arrays were undefined behaviour and the multiArray[0] = new int[3] { 1, 2, 3} syntax :) – user99999991 Sep 15 '14 at 22:01
  • @juanchopanza - not a duplicate of that question. It only answered part, and even then, was insufficient in what I was asking. I specifically addressed that I know how to allocate it on the heap. I didn't know how to allocate it on the heap using the syntax I needed as well as if it was even necessary. Neither of which are addressed in your link. – user99999991 Sep 16 '14 at 01:58
  • @CareyGregory - I wasnt trying to AVOID using new as you imply. I specifically said in my question I wasnt sure if I had to or not. it is no big deal for 1, 2, 3 ; 3, 4, 5; 6,7,8 ; But if it was a larger set, such as ones obtained from some complex function that you can't just loop over, and you were dealing with a larger 2D array for example, it would be a pretty big deal to sit and initialized each set of indices ( say 20x20) each line! You can at least half that with { } notation I was looking for. – user99999991 Sep 16 '14 at 02:04
  • I didn't say (or think) you were trying to avoid using `new`. But you said explicitly you were trying to avoid the runtime initialization of the arrays. My comment was to say you really don't need to worry about trivial initializations like that. Unless the arrays you're initializing have elements numbering at least in the thousands, or the initialization function is called thousands of times, you really don't need to worry about such things. A 20x20 array can be initialized in a `for` loop in microseconds on any modern processor. – Carey Gregory Sep 16 '14 at 03:55
  • @user999999928 You obviously did not know how to dynamically allocate a "2D array" (i.e. an a dynamically allocated array full of pointers to dynamically allocated arrays.) That much is clear from the code you posted. If you have N problems in your code, you should solve the first, most basic one, and then move on once you have done that. – juanchopanza Sep 16 '14 at 05:29
  • @juanchopanza : if you actually read my question in its entirety - I LINKED to an article that specifically demonstrates allocating a 2D array with new. And I specifically said I didn't want to do it in the manner he showed. "But, back in my equivalent of foo(), he manually allocated the array to the heap with the new operator with a loop as opposed to { 1, 2, 3 } initializing an array then assigning it like I did. http://www.cplusplus.com/forum/articles/7459/" I specifically stated I wanted to allocate on the heap, but wanted the default initializers too. You either didn't read, or misread – user99999991 Sep 16 '14 at 16:17
  • @juanchopanza - and not to mention, the FIRST thing I said about the code was that it probably wasn't allocating on the heap. I know how to allocate a 2D array on the heap with new. What I didn't know was how to do it with { } notation (I thought maybe it did that for me), or if there was a different way entirely to do this better besides just using a vector. Don't tell me what I "obviously did not know" when I specified otherwise. I went to the trouble of detailing that inner paragraph for a reason. – user99999991 Sep 16 '14 at 16:20
  • Maybe you can convince someone else to re-open, or flag the question for moderator attention. You lead your question with a colossal failure to properly allocate the "2D array" you claim to know how to allocate. You could have been clearer about what you were asking (and that doesn't mean writing a 200 page epic.) – juanchopanza Sep 16 '14 at 16:25
  • I lead the question with the supposed colossal failure b/c I wasnt sure if it was a colossal failure or not. I know how to allocate the to the heap, but what I wasn't sure was if the { } notation was doing it for me (b/c it was working but it felt wrong because I KNEW how to normally allocate it, which I felt was clear but apparently not) Hence why I lead the question with it, and why I added onto it that I wanted to keep the { } notation. That's what I was looking for if it was an option. "I really don't want to loop over the multiArray, call new on each index, then manually assign each int." – user99999991 Sep 16 '14 at 16:35

1 Answers1

2

In order to allocate an array on the heap using {} notation (only in c++11 or later)

int *a = new int[4]{1,2,3,4};

so that means that in order to allocate a multidimentional array on the heap:

int **b = new int*[2]{new int[2]{1,2}, new int[2]{3,4}};

the foo function should be:

int ** foo()
{
    int **multiArray = new int*[3]{new int[3]{1,2,3}, new int[3]{4,5,6}, new int[3]{7,8,9}};
    return multiArray;
}

if you can't use c++11 then there is no easy way to do this. You would need to allocate the memory, and then fill it with values.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
while1fork
  • 374
  • 4
  • 15