Thread: Newbie question: Right way of creating a matrix using the new operator?

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    5

    Question Newbie question: Right way of creating a matrix using the new operator?

    Hi,

    I'm trying to dynamically create a matrix, let's call it M, which can be accesed using the usual M[i][j] notation. That's it, it should behave as if I had declared it as a double M[5][5], except the size should be a variable rather than 5.

    This is the simplest example:

    Code:
    #include <iostream.h>
    
    void createMatrix(int size) {
    
    	double *M = new double[size*size]; // doesn't work :(
    
    	/*
    	// This does work, but is really awful... there's got to be a better way!
    
    	double **M = new double*[size];
    
    	for (int k = 0; k < size; k++)
    		M[k] = new double[size];
    
    	*/
    
    	// this MUST work:
    
    	for(int i = 0; i < size; i++)
    		for(int j = 0; j < size; j++)
    			M[i][j] = 3.141592;         // whatever
    
    	delete[] M;
    }
    
    int main() {
    	int n;
    
    	cout << "Size of the matrix? ";
    	cin >> n;
    
    	createMatrix(n);
    
    	return 0;
    
    }
    Please, tell me there's a better solution that the horrible hack I did!!


  2. #2
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    The double pointer method is the only way I know that you can dynamically create a 2*2 array besides using a container. Oh and it is <iostream> and not <iostream.h> and put it in the std namespace.
    Woop?

  3. #3
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Code:
    void createMatrix(int size)
    {
            double **M =  new double*[size];
            for(int i=0; i < size; i++)
                    M[i] = new double[size];
    
            // Do something with it here
    
            for(int i=0; i < size; i++)
                    delete[] M[i];
            delete[] M;
    }
    Another why using vectors:
    Code:
    void createMatrix(int size)
    {
            vector< vector<double> > M;
            M.resize(size);
            for(int i=0; i < size; i++)
                    M[i].resize(size);
    }

  4. #4
    Registered User
    Join Date
    Apr 2005
    Posts
    5
    Thanks for the reply... does anybody else know if the right way of dynamically creating a n*n array is:

    Code:
    	double **M = new double*[size];
    
    	for (int k = 0; k < size; k++)
    		M[k] = new double[size];
    Because this is really ugly syntax, and, if I understand memory allocation correctly, awfully inefficient because not only we have significant overhead allocating memory in a loop but we'll also, with all probability, end with a fragmented matrix, as there's no reason to expect those allocations will put our new arrays contiguously in memory.

    This program is supposed to use a very large matrix.

  5. #5
    Registered User
    Join Date
    Apr 2005
    Posts
    5
    Quote Originally Posted by Thantos
    Code:
    void createMatrix(int size)
    {
            double **M =  new double*[size];
            for(int i=0; i < size; i++)
                    M[i] = new double[size];
    
            // Do something with it here
    
            for(int i=0; i < size; i++)
                    delete[] M[i];
            delete[] M;
    }
    Thanks for the correction... one memory leak less

    [QUOTE]
    Another why using vectors:
    Code:
    void createMatrix(int size)
    {
            vector< vector<double> > M;
            M.resize(size);
            for(int i=0; i < size; i++)
                    M[i].resize(size);
    }
    This is much better... but, can I access individual members of M with the M[i][j] notation if I use this? Also, is this what you guys mean when you said "using a container"?

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    but, can I access individual members of M with the M[i][j] notation if I use this?
    ...and how many seconds would that take to test?

    Also, is this what you guys mean when you said "using a container"?
    Yes.

  7. #7
    Registered User
    Join Date
    Apr 2005
    Posts
    5
    Quote Originally Posted by 7stud
    ...and how many seconds would that take to test?
    Ok, I tested it... seems to work great

    But what about efficiency? It seems to me this is the same thing I was doing initially but with a better syntax, which probably means the overhead and fragmentation problems I wrote about are still there...

    And there's no need to deallocate memory while using containers... right?

  8. #8
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Ya all of the deallocation is taken for you with the containers within the destructor of the container you are using. I am not sure what you mean about fragmentation when using dynamic memory but I don't think so.
    Woop?

  9. #9
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Because calls of new and delete are generally slow, thers is one way I like:
    Code:
            //Allocate the actual data
    
            int* rawData = new int[rows*cols];
     
    	//Allocate pointers to the data
    	int** data = new int*[rows];
     
    	//Point the pointers into the data
    	for (int i=0; i < rows; ++i)
    	    data[i] = &rawData[cols*i];
    I hope this code will not confuse you.

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  10. #10
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    But what about efficiency? It seems to me this is the same thing I was doing initially but with a better syntax, which probably means the overhead and fragmentation problems I wrote about are still there...
    That's what I was wondering about, too.

    And there's no need to deallocate memory while using containers... right?
    The class takes care of all that: you can expand or contract the vector at will as well using insert(), pushback(), and erase().

  11. #11
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    I am not sure what you mean about fragmentation when using dynamic memory but I don't think so.
    I think he suspects that since the allocations take place at different times, e.g. one allocation per loop iteration, that the allocated memory will not necessarily be contiguous. My first question is: since dynamically allocated memory is allocated on the heap, is there a way for any other processes to allocate memory on the heap in between a for-loops allocations? My second question is: does it even matter whether the memory is contiguous or not. The look up is done with a pointer, so is it even relevant where the actual arrays are located?
    Last edited by 7stud; 04-25-2005 at 04:24 AM.

  12. #12
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    Arrays are always contiguous in memory. And yes, it does matter for arrays. When you code something like a[5], that tells the computer to go start at *a, or a[0], and go over five. Therefore, those array indices must be contiguous in memory.

    Container classes are another story, however. You could implement a container to act like an array that's really a linked list or hash under the hood.
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  13. #13
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    A multi dimensional array allocated like this probably won't be contigious. But thats ok as each dimension will be contigious onto itself. It only becomes a problem when you try to treat a multi dimensional array as a single dimensional array.

    Container classes are another story, however. You could implement a container to act like an array that's really a linked list or hash under the hood.
    Except vectors require that &v[1] == (&v[0] + 1)

  14. #14
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    Quote Originally Posted by Thantos
    Except vectors require that &v[1] == (&v[0] + 1)
    I wasn't talking about the vector class. I know that the STL containers have restrictions on speed and space and such. That doesn't stop someone from creating a class with the much of the interface of a vector with another underlying container -- even if that does mean differing performance.

    I was just trying to point out that when using a class, one shouldn't overly concern oneself with the underlying structure.
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  15. #15
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    >>double *M = new double[size*size]; // doesn't work

    This does work if you index it properly. instead of indexing M[x][y], you use M[ x*size + y ].

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird errors.
    By Desolation in forum C++ Programming
    Replies: 20
    Last Post: 05-09-2007, 01:10 PM
  2. Replies: 6
    Last Post: 11-08-2005, 03:05 PM
  3. Replies: 3
    Last Post: 04-29-2005, 02:03 AM
  4. Help on scrolling matrix for a newbie
    By Saturn V in forum C++ Programming
    Replies: 1
    Last Post: 06-04-2002, 09:12 PM