-1

I've got this multi dimensional dynamic array, and I can print it out as six rows of six columns of zeros, but I can't return it as the same. The function is supposed to initialize an array that can be passed to other functions. What am I doing wrong here? I commented out the "cout" portions because that's not what I need to do. Thanks!

long initializeArray (void)
{
    int i = 0, j = 0;
    typedef int* rollarray;
    rollarray *m = new rollarray[6];
    for (int i = 0; i < 6; i++) m[i] = new int[6];
    while (j < 6)
    {
        while (i < 6)
        {
            m[i][j] = 0;
            //cout << m[i][j] << " ";
            i++;
        }
        //cout << endl;
        i = 0;
        j++;
    }
}
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
bc8787
  • 41
  • 1
  • 6
  • This is C++ don't use pointers, use the stl containers – aaronman Jul 18 '13 at 00:08
  • You can just pass in a pointer; In your current case you are using local variable `*m` and returning it is non sense. – ludesign Jul 18 '13 at 00:09
  • 3
    Where is your `return` statement, or your out parameter? It is hard to return anything without one or the other. – jxh Jul 18 '13 at 00:21
  • Use vector> to create 2d array of integers. It's loads easier. You just return the variable and that's it. – Neil Kirk Jul 18 '13 at 00:28
  • 1
    @ludesign: Returning `m` would be fine, since it's dynamically allocated. Declaring a function to return `long` when you want to return `int **` is not so fine, though, and neither is forgetting to return anything at all. But as others have said, using C++ properly and using standard containers is often best for real-world purposes. – Crowman Jul 18 '13 at 00:33
  • @PaulGriffiths - I agree. Shame on me. Didn't saw the `new rollarray[6]` piece of code when wrote the comment. – ludesign Jul 18 '13 at 00:42
  • @aaronman mind your manners – Ryan Haining Jul 18 '13 at 01:06
  • @RyanHaining did you delete my "useful" comments – aaronman Jul 18 '13 at 01:07
  • are you sure a [dynamic array](https://en.wikipedia.org/wiki/Dynamic_array) is what you want, and not a dynamically allocated array? – Ryan Haining Jul 18 '13 at 01:10
  • @aaronman I don't have that kind of power – Ryan Haining Jul 18 '13 at 01:12

4 Answers4

4

You should declare your function:

int** initializeArray(void)

and then:

return m;

at the end, if you must do it this way. Don't forget you'll have to manually tell anything else that uses this pointer that it's a 6 x 6 array, and don't forget to delete[] all those arrays when you're done with them.

Crowman
  • 25,242
  • 5
  • 48
  • 56
  • +1 because this is the only answer that actually answers the question. However, I agree that using a dynamic array of dynamic arrays may not be the correct approach in the first place, unless you really need to handle rows of different size. – Boris Dalstein Jul 18 '13 at 00:51
  • This is also the only answer that does not answer the following 5 questions related to problems with raw pointers, memory leaks, undefined behaviour, segmentation faults etc., because of raw pointer usage. To learn from mistakes is of course desirable if OPs interest is of academic nature. Without a doubt, will he learn something about pointers if he keeps on going but it may also be the case that going directly on the correct path leads to a better feeling for "the C++ way of doing things". As Stroustrup says: "Don't hack; concentrate on algorithms!" (or similar I don't remember exactly.) – Pixelchemist Jul 18 '13 at 01:04
  • I agree to an extent, and I don't think it's necessary to spend a lot of time learning about the 'bad old days' before doing things the C++ way. However, like it or not, pointers are a part of C++, and any well-rounded C++ programmer is going to have to learn how to work with them properly eventually. `std::vector` isn't going to help much for people who want to access hardware, or write their own efficient containers, for instance. – Crowman Jul 18 '13 at 01:14
  • @PaulGriffiths I totaly agree. I had a lengthy comment-discussion on that topic in May where I took up exactly this position. – Pixelchemist Jul 18 '13 at 01:28
2

I won't repeat my complete answer on why dynamic two-dimensional matrices (and this clearly is one) aren't the way to go in C++.

Answer on: 1D or 2D array, what's faster? (Start reading @ The long answer, or why dynamic 2 dimensional data storage (pointer-to-pointer or vector-of-vector) is "bad" for simple / small matrices.)

You'll find:

  • A rather detailed explanation why you don't want to use pointer-to-pointer dynamic arrays
  • An example class for simple matrix objects

You won't even need a function that initializes your data to zero. Just write

matrices::simple<int> matrix_object(6, 6);

to get a zero-initialized matrix of size 6x6.

Now you can access the elements via

matrix_object(0,1) = 2; // sets 2nd element of first row to 2

The "C++ way" of writing the matrix to a stream would involve defining operator<< for that class like:

template<typename T>
std::ostream & operator<< (std::ostream &stream, matrices::simple<T> const & matrix)
{
  typedef typename matrices::simple<T>::size_type size_type;
  for (size_type i(0u); i<matrix.rows(); ++i)
  {
    for (size_type j(0u); j<matrix.cols(); ++j) 
         stream << std::setw(4) << std::right << matrix(i,j);
    stream << std::endl;
  }
  return stream;
}

You could easily output your matrix this way by writing:

std::cout << matrix_object << std::endl;

Together with the previous snipptes this will output:

   0   2   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0

If you want to keep going for pointers you'll have to address several issues in your code. I've added two parameters to enable other sizes but the can be replaced by 6 again if desired.

int** new_initialized_array (size_t const rows, size_t const cols)
{
    typedef int* rollarray;
    rollarray *m = new rollarray[rows];
    size_t allocated_arrays(0u);
    try
    {
      for (size_t i(0u); i < rows; ++i) 
      {
        m[i] = new int[cols];
        ++allocated_arrays;
        for (size_t j(0u); j<cols; ++j) m[i][j] = 0;
      }
    }
    catch (std::bad_alloc & e)
    {
      for (size_t i(0u); i < allocated_arrays; ++i) delete[] m[i];
      delete[] m;
      throw;
    }
    return m;
}

The issues I addressed:

  1. To return a pointer, the function must have a return type that actually is a pointer (long is an unsigned value).
  2. You need to track you allocations. If one of them fails you'll need to roll-back the rest to avoid memory leaks.
  3. You don't need the double-while loop. You have your outer loop already present (the one you do you allocation in) so you only need an inner loop to set the initial values for your array.
  4. Last but not least I renamed the function. It doesn't actually "initialize" an existing array but creates a new, initialized one.

I can only recommend to read the link above (or any other resource about how to handle 2D-data according to RAII).

Community
  • 1
  • 1
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
2

C++ :)

#include <vector>
#include <iostream>

std::vector<std::vector<int> > initializeVector() {
    std::vector<std::vector<int> > vec(6, std::vector<int>(6));

    int i = 0, j = 0;
    while (i < 6) {
        while (j < 6) {
            vec[i][j] = i+j;
            j++;
        }

        j = 0;
        i++;
    }

    return vec;
}

int main(int argc, char* argv[]) {
    std::vector<std::vector<int> > g_vec = initializeVector();

    int i = 0, j = 0;
    while (i < 6) {
        while (j < 6) {
            std::cout << g_vec[i][j] << std::endl;
            j++;
        }

        std::cout << "-----------------" << std::endl;
        j = 0;
        i++;
    }

    return 0;
}
ludesign
  • 1,353
  • 7
  • 12
1

Is it a homework assignment? Or are you trying to do Matrix Algebra in C++?

If it's not homework, then check first if something exists that is both easier for you to use and is more performant. Pixelchemist made good points, so you should be able to use someone else's code to do your work for you.

Take a look into the Eigen library: http://eigen.tuxfamily.org/dox/TutorialAdvancedInitialization.html

// Initializing a 6x6 dynamic size matrix with zeros, adapted from documentation
using namespace Eigen;
ArrayXXf a3 = ArrayXXf::Zero(6, 6);
std::cout << a3 << "\n";
Prashant Kumar
  • 20,069
  • 14
  • 47
  • 63